I want to hook into a DLL library and manipulate the arguments passed into it and manipulate its behavior. I don't want to have to maintain a separate fork by rebuilding the library and tracking changes. Instead, I want to use my library as a way to just pass calls on to the target library.
I can see what functions are exposed in the DLL but I only need to implement a subset of these. Is there a way to use a debugger to monitor and get a list of functions being called?
What you want to make a is a proxy DLL. You replace the original DLL with yours and rename the original, then you LoadLibrary() the original renamed DLL. For functions you don't want to log or modify, you just pass through to the real DLL function. Otherwise you modify the arguments and then pass it through.
There are many tools which can help you generate a proxy DLL
https://github.com/maluramichael/dll-proxy-generator
https://github.com/zeroKilo/ProxyDllMaker
https://github.com/kevinalmansa/DLL_Wrapper
Related
I have an ActiveX component in XE2 that connects to a database to handle transaction processing, and it includes a check of its version against that of the database to determine if they are compatible.
Unlike C#, where the AssemblyVersion attribute can be obtained at runtime using the Application.ProductVersion property, Delphi XE2 has no such built-in property for getting the version information included in the project options, with the preferred method being to use GetFileVersionInfo, passing in the full path to the program, or in this case the OCX.
Originally the OCX was always installed to the Windows System path but we have changed our installation process so that the OCX is installed to the same folder as the executable that uses it, which is a location determined by the user.
What I need is a consistent method that I can use from within the OCX code to obtain the installation folder from the registry across the multitude of Windows environments. I assume it would have something to do with the GUID's defined in the _TLB.pas file.
You don't need to query the Registry at all. The OCX can retreive its own filename by passing Delphi's global HInstance variable as the module handle to the Win32 API GetModuleFileName() function, then it can pass that filename to GetFileVersionInfo().
Although, a better way for the OCX to access its own version, without resorting to GetFileVersionInfo(), is to use Find/Load/LockResource() to access its own version resource directly, then no filename is needed at all. You can copy the version resource data into a temp buffer and pass that to VerQueryValue() to retrieve the resource's VS_FIXEDFILEINFO structure (retrieving anything else from the resource gets a bit trickier because GetFileVersionInfo() prepares certain lookup data that VerQueryValue() then uses).
You certainly don't need to use the registry here. Not least because there could potentially be multiple versions of the DLL on the machine, because you are installing to the executable directory of any program that uses the DLL.
You could certainly read the version resource as Remy describes. But another alternative would be to include a constant in your program that encodes the database version compatibility.
const
DatabaseVersion = 1;
Check this constant against the value read from the database and fail if not compatible.
To me this makes a little more sense as it separates the version of the DLL from the version of the database. The two are not necessarily linked. You could, and probably do, update the DLL without changing the database structure.
I have learned that you can:
Convert a .DLL file into a .DEF file, which includes its exports
(Edit: This doesn't work with many conventions)
Convert a .DEF file into a .LIB file, which you can use to link to the DLL
Why can't (most) linkers link to a DLL given only a .DEF file, instead of a .LIB file?
Ultimately, the answer here is 'because noone wanted it badly enough and it doesn't really help anything'.
The DEF file is an input file that creates an import lib for the DLL. And then, later, when the DLL is being consumed by another link, the importlib is itself an input. The importlib looks like something special on the outside, but when you look at the inside it's really just a slightly special lib with objects in it.
It totally would be possible to modify the linker to take a def file (or a DLL, for that matter) directly.
But the design centre of the linker is that it takes objects as inputs and outputs a PE executable. So taking a DEF or DLL as an input goes outside the design pattern.
Beyond that it'd be rather pointless - allowing the linker to take a DEF file or DLL as input would neither enable any important new scenarios, nor does leaving this feature out block anything. Converting a DEF file you have (even without the actual DLL) into a usable importlib is the work of a few moments (simply create fake empty function for each DEF entry and link that). So there's no reason to add the ability to link a DEF file directly.
Martyn
In terms of MSVC, .lib files are always static libraries. They get linked in as a compilation unit along with all your compiled .c/.cpp files, so all of the library's code is included in your final executable.
Some .lib files, however, (in particular most of the Windows system ones) merely contain stubs which tell the OS to load the desired DLL at loadtime and then the stubs route function calls to the DLL. But, those stubs are statically linked into your executable. Your program will then use DLLs (and gain all the advantages and disadvantages thereof), but since the named DLL functions it requires are happily located in the .lib (and thus actually located in the executable itself), your code doesn't have to know it's using a DLL (specifically using declspec(dllimport)).
A .def file is merely used as a sort of "settings" or "configuration" file during the creation of a .dll to specify what functions the file should export. It cannot be linked to, as it doesn't really describe anything that the linker understands.
You do not convert a dll to a DEF file. The DEF just indicates which dll functions will be accessible from the outside, exported.
From the docs:
A DLL file has a layout very similar to an .exe file, with one
important difference — a DLL file contains an exports table. The
exports table contains the name of every function that the DLL exports
to other executables. These functions are the entry points into the
DLL; only the functions in the exports table can be accessed by other
executables. Any other functions in the DLL are private to the DLL.
The exports table of a DLL can be viewed by using the DUMPBIN tool
with the /EXPORTS option.
You can export functions from a DLL using two methods:
Create a module definition (.def) file and use the .def file when
building the DLL. Use this approach if you want to export functions
from your DLL by ordinal rather than by name.
Use the keyword __declspec(dllexport) in the function's definition.
When exporting functions with either method, make sure to use the
__stdcall calling convention.
Use the provided link to learn more about exporting from your dll's.
I think you got down voted because your point is not really clear, at least not to me. Also check this. It explains how to choose the export method.
Mehrdad, this isn't always a question of how to LINK to a DLL, as I, personally have NEVER linked a DLL using a .DEF file. What I HAVE done is take someone else's DLL, and very painstakingly constructed a header file, or rather, function prototypes that I could use with
LoadLibrary() in C, Declare Function ... Lib "Foo.dll" Alias "OrdinalName" in VB, and
[DllImport()] in C#.
Of course, this is RARELY done, as if you are using a DLL for something, normally you have permission to do so, and the authors provide the .lib's, and the headers to go with the binary DLL file.
I've never done the exact techniques you speak of, by converting a .DEF info a .LIB, etc... But, I suppose it would be easy to take a lib, or the DLL itself and export .DEF from it. Now, THAT I actually HAVE done, in a project where the DLL code was built with a vbScript that took code from the main project, and created an API out of all the existing, compiled, and tested code. This level of complication was only done because I had no idea what functions were going to BE in the DLL, as the main project could change at any time, so a static .DEF file would have never worked. So, I had to build the DLL once, capture the dimpbin /exports, undecorate the functions, and then build the .DEF file, and re-link the DLL.
If you find yourself in that type of situation, perhaps you need to re-think your original designs, and fix the problem from there...
As for .LIB files, USUALLY you'd only NEED those for static linkage, but they are also used when the .H file is available, often making debugging a just a little nicer...
A change needs to be made in a DLL. The DLL was originally coded in VB6 (not by me), and the source code lost.
It is very simple in its functionality, so I recreated it from scratch, but I only have access to VB Express 2008.
I created it first as a normal DLL then realized it had to be a COM DLL. Fortunately, an excellent article at http://www.codeproject.com/KB/COM/nettocom.aspx tells me how.
But, I don't know anything about GUIDs...
Should I use the same GUID as the original DLL or not? Does it make any difference?
Edit: Does it really matter since it's a COM DLL? It is called into by an Active X control & I can see no reference in the web page to the GUI ... (but I'm just a n00b, so what do I know? ;-)
If you want this library to be a direct replacement of the original and it is fully binary compatible (all interfaces are unchanged) - then yes, you should use the same GUIDs for the class ids and interface ids. If you don't do that users of the original library will not be able to use yours without recompiling their programs.
Beware that binary compatibility is a must for reusing the GUIDs. If you break any interface - change its id and the id of the class implementing it and recompile the client.
The GUIDs acts as a kind of identifier for your COM object and DLL. If you use the same GUID you need to register your new DLL so that the location is updated (i.e. if you don't place it exactly in the same spot and have recreated all interfaces the old DLL previously had registered).
The cleaner approach is to generate a new GUID and modify the caller to use the new GUID/DLL instead.
I am using dev c++ and i need to call a function which has some butons and edit boxes created using windows.h through another program which uses graphics functions and both files exist in a project and i am unable to do it..can any one help me please...
From what I gather, you have a function that creates some GUI components and needs to be called from two different programs. If this is the case, one option is to create a separate .DLL project that makes a run-time library that can be shared with the other two programs.
I want to create a small app to add and remove user defined context menu entries from the registry. To make this, somehow I need to get the CLSID of an arbitrary DLL so I can back up previous entries if they exist before writing new ones.
Although regsrv32 somehow manages to create this magical number, I didn't find any way to get that number myself.
I hope there is something better than this:
scanning registry for the DLL name
if not found, register it, scan again, and then unregister it again
If the DLL has been renamed, I can see a possibility for problems.
You could consider calling LoadTypeLibEx on the DLL specifying REGKIND_NONE and then examine get the TypeLibInfo information available via the ITypeLib interface passed back to you.
There's some information about this sort of thing on MSDN. It's an old VB6-focused link but has useful information about inspecting COM components in this way.
You could try to use RegOverridePredefKey() to intercept what regsvr32 does to the registry - call RegOverridePredefKey(), then reproduce what regsvr32 does - LoadLibrary() the COM server, call DllRegisterServer() - then inspect the changes done. With RegOverridePredefKey() you will isolate the changes and not let them become persistent.