I created a wrapper DLL using a DEF file for describing its EXPORTS.
From the original DLL's exports (generated using dumpbin):
EXPORTS
??0FooBar##QAE#ABV0##Z #1
From the created DEF file for my wrapper DLL:
EXPORTS
??0FooBar##QAE#ABV0##Z=__E__0__ #1
When checking the resulting wrapper DLL using OllyDbg, I can see that the export actually gets changed towards:
Names in FooBarDLL, item 0
Address=0F085685
Section=.text
Type=Export
Name=??0FooBar
As you see, it is missing that additional garbledegock (##QAE#ABV0##Z) usually generated by Microsoft Visual C++ for this type of a class/function/parameter combination.
To make sure that this is not a user error on the usage of OllyDbg, I checked the original DLL's exports as well and to no surprise those looked just like the stuff I was expecting:
Names in FooBarDLLOriginal, item 1
Address=1003A800
Section=.text
Type=Export
Name=??0FooBar##QAE#ABV0##Z
As I need my wrapper DLL to look exactly like the original DLL, this result is obviously no good.
How can I prevent Visual C++ from ignoring fragments of my DEF exports definitions?
I have tried to play with many compiler and linker options but utterly failed in getting any closer to my goal.
I finally got it working.
As Hans Passant noted, the linker somehow does handle #-signs within export definitions in a way that I found hard to grasp...
My observations:
Mangled C++ function (??0FooBar##QAE#ABV0##Z) forwarded to an unmangled (extern "C") function (__E__0__)
=> C++ function mangling gets cropped at the first #-sign (??0FooBar)
Mangled C++ function (??0FooBar##QAE#ABV0##Z) forwarded to a mangled (extern "C" __declspec(dllexport)) function (___E__0__#4)
=> C++ function mangling stays intact
This would be my initial test-case, now being close enough to my initial goal.
From the DEF file of the wrapper:
EXPORTS
??0FooBar##QAE#ABV0##Z=___E__0__#4 #1
From the wrapper DLL's exports (generated using dumpbin):
ordinal hint RVA name
1 0 00001000 ??0FooBar##QAE#ABV0##Z = ___E__0__#4
2 1 00001000 ___E__0__#4 = ___E__0__#4
What really astonished me is that the export from ordinal 1 remains invisible when using OllyDbg to read the exports table. Still, when loading the DLL (LoadLibrary) and resolving the address of that function using GetProcAddress(hDLL, "??0FooBar##QAE#ABV0##Z"), things work just fine.
So I now have a DLL that wraps the original one, using a functionally identical exports table. It now shows an additional export of my proxy implementation, but that is no problem for my purposes. That way it is possible to create a proxy DLL that intercepts and, if needed, enhances the original implementation even when C++ mangling is involved. I somehow feel that I overcomplicated things a little but hey, it works.
For functions that I entirely pass through, I simply create a forwarding export in my DEF file, looking like this:
??BarFoo#WhoCares###Z = OriginalDllName.??BarFoo#WhoCares###Z
This question (and others like it) relate to creating proxy DLLs automatically using the Code Project WRAPPIT tool. The solution using the observation from Till, is to:
Always declare the wrapper function to be __stdcall so that it gets decorated with a leading _ and trailing #0, and then use that in the .def file so that the original function decoration (if any) is preserved.
(When/if you replace the wrapper with a real function, you need to remember to change the call convention from __stdcall to the one needed, as well as remove __declspec(naked), add argument declarations, change or remove the .def file declaration to match etc.)
Wrapper .cpp snipet:
// _OriginalFunction#12
extern "C" __declspec(naked) void __stdcall __E__0__()
{
__asm
{
jmp p[0*4];
}
}
.def file:
EXPORTS
_OriginalFunction#12=___E__0__#0 #1
etc.
I modified my version of the WRAPPIT tool to do this automatically:
165c165
< fprintf(fdef,"%s=%s #%u\r\n",v[i].en,v[i].in,v[i].o);
---
> fprintf(fdef,"%s=_%s#0 #%u\r\n",v[i].en,v[i].in,v[i].o);
167c167
< fprintf(fdef,"%s=%s #%u NONAME\r\n",v[i].en,v[i].in,v[i].o);
---
> fprintf(fdef,"%s=_%s#0 #%u NONAME\r\n",v[i].en,v[i].in,v[i].o);
225c225
< fprintf(fcpp,"// %s\r\nextern \"C\" __declspec(naked) void %s %s()\r\n",v[i].en,argv[3],v[i].in);
---
> fprintf(fcpp,"// %s\r\nextern \"C\" __declspec(naked) void %s %s()\r\n",v[i].en,"__stdcall",v[i].in);
Related
I created a wrapper DLL using a DEF file for describing its EXPORTS.
From the original DLL's exports (generated using dumpbin):
EXPORTS
??0FooBar##QAE#ABV0##Z #1
From the created DEF file for my wrapper DLL:
EXPORTS
??0FooBar##QAE#ABV0##Z=__E__0__ #1
When checking the resulting wrapper DLL using OllyDbg, I can see that the export actually gets changed towards:
Names in FooBarDLL, item 0
Address=0F085685
Section=.text
Type=Export
Name=??0FooBar
As you see, it is missing that additional garbledegock (##QAE#ABV0##Z) usually generated by Microsoft Visual C++ for this type of a class/function/parameter combination.
To make sure that this is not a user error on the usage of OllyDbg, I checked the original DLL's exports as well and to no surprise those looked just like the stuff I was expecting:
Names in FooBarDLLOriginal, item 1
Address=1003A800
Section=.text
Type=Export
Name=??0FooBar##QAE#ABV0##Z
As I need my wrapper DLL to look exactly like the original DLL, this result is obviously no good.
How can I prevent Visual C++ from ignoring fragments of my DEF exports definitions?
I have tried to play with many compiler and linker options but utterly failed in getting any closer to my goal.
I finally got it working.
As Hans Passant noted, the linker somehow does handle #-signs within export definitions in a way that I found hard to grasp...
My observations:
Mangled C++ function (??0FooBar##QAE#ABV0##Z) forwarded to an unmangled (extern "C") function (__E__0__)
=> C++ function mangling gets cropped at the first #-sign (??0FooBar)
Mangled C++ function (??0FooBar##QAE#ABV0##Z) forwarded to a mangled (extern "C" __declspec(dllexport)) function (___E__0__#4)
=> C++ function mangling stays intact
This would be my initial test-case, now being close enough to my initial goal.
From the DEF file of the wrapper:
EXPORTS
??0FooBar##QAE#ABV0##Z=___E__0__#4 #1
From the wrapper DLL's exports (generated using dumpbin):
ordinal hint RVA name
1 0 00001000 ??0FooBar##QAE#ABV0##Z = ___E__0__#4
2 1 00001000 ___E__0__#4 = ___E__0__#4
What really astonished me is that the export from ordinal 1 remains invisible when using OllyDbg to read the exports table. Still, when loading the DLL (LoadLibrary) and resolving the address of that function using GetProcAddress(hDLL, "??0FooBar##QAE#ABV0##Z"), things work just fine.
So I now have a DLL that wraps the original one, using a functionally identical exports table. It now shows an additional export of my proxy implementation, but that is no problem for my purposes. That way it is possible to create a proxy DLL that intercepts and, if needed, enhances the original implementation even when C++ mangling is involved. I somehow feel that I overcomplicated things a little but hey, it works.
For functions that I entirely pass through, I simply create a forwarding export in my DEF file, looking like this:
??BarFoo#WhoCares###Z = OriginalDllName.??BarFoo#WhoCares###Z
This question (and others like it) relate to creating proxy DLLs automatically using the Code Project WRAPPIT tool. The solution using the observation from Till, is to:
Always declare the wrapper function to be __stdcall so that it gets decorated with a leading _ and trailing #0, and then use that in the .def file so that the original function decoration (if any) is preserved.
(When/if you replace the wrapper with a real function, you need to remember to change the call convention from __stdcall to the one needed, as well as remove __declspec(naked), add argument declarations, change or remove the .def file declaration to match etc.)
Wrapper .cpp snipet:
// _OriginalFunction#12
extern "C" __declspec(naked) void __stdcall __E__0__()
{
__asm
{
jmp p[0*4];
}
}
.def file:
EXPORTS
_OriginalFunction#12=___E__0__#0 #1
etc.
I modified my version of the WRAPPIT tool to do this automatically:
165c165
< fprintf(fdef,"%s=%s #%u\r\n",v[i].en,v[i].in,v[i].o);
---
> fprintf(fdef,"%s=_%s#0 #%u\r\n",v[i].en,v[i].in,v[i].o);
167c167
< fprintf(fdef,"%s=%s #%u NONAME\r\n",v[i].en,v[i].in,v[i].o);
---
> fprintf(fdef,"%s=_%s#0 #%u NONAME\r\n",v[i].en,v[i].in,v[i].o);
225c225
< fprintf(fcpp,"// %s\r\nextern \"C\" __declspec(naked) void %s %s()\r\n",v[i].en,argv[3],v[i].in);
---
> fprintf(fcpp,"// %s\r\nextern \"C\" __declspec(naked) void %s %s()\r\n",v[i].en,"__stdcall",v[i].in);
I'm trying to write a forwarding library for libEGL.dll so I can catch calls being passed through it for debug.
The problem is the library is missing 2 methods NvEglGetStdProcAddress and NvEglRegClientApi.
This is a C library built for Arm7 (WinCE). The header file I have for libEGL doesn't include these 2 methods so I have no idea what the signature is in order to forward the calls.
Is there any way of forwarding the calls without knowing the signature?
Could I disassemble the dll and look for the parameters being popped from the stack?
DumpBin shows these at RVA 0x217C and Ox1E5C, /ALL /DISASM shows the .text section starting at 0x11000. How do I translate between these two offsets?
I'm guessing this wouldn't work, Would it just leave the parameters on the stack and then mangle them slightly with the local variable? What would happen to the return value (if there is one?)
typedef void (*NvEglGetStdProcAddressFunc) (void);
void NvEglGetStdProcAddress()
{
NvEglGetStdProcAddressFunc ptr = (NvEglGetStdProcAddressFunc)GetProcAddress(hInst, _T("NvEglGetStdProcAddress"));
ptr();
}
You can simply forward export calls.
So my debug libEGL.dll .def file now has two extra lines at the top of it
; libEGL.def
EXPORTS
NvEglGetStdProcAddress = libEGLOld.NvEglGetStdProcAddress
NvEglRegClientApi = libEGLOld.NvEglRegClientApi
eglBindAPI
eglBindTexImage
...
A colleague of mine tested this and verified it works, although it also requires the ordinal to be specified
I have a dll with exporting function
extern "C" __declspec(dllexport) IDriver * __stdcall GetDriver()
There is a programm which is written on Delphi. It can't see the function GetDriver().
It's double awful because I can not get and modify sources of this program.
What may be the reason of successful loading my dll (according log file) and failed call exporting function? Thank you.
Window 7 x64, Visual Studio 2010, C++ project for x86 target
The most likely explanation is that the function will have been exported with a decorated name. I'd expect it to have been exported with the name GetDriver#0. So you could import it like this:
function GetDriver: IDriver; stdcall; external 'DllName.dll' name 'GetDriver#0';
Use a tool like Dependency Walker to check the exact name used to export the function.
If you cannot modify the Delphi code, then you'll need to make your C++ DLL match. Do that by using a .def file which allows you control over the exported name.
The other problem you will face is that Delphi's ABI for return values differs from that used by most other tools on the Windows platform. Specifically a return value is semantically a var parameter. On the other hand, your C++ compiler will regard the return value as an out parameter. My question on Delphi WideString return values covers exactly this issue.
Because of this, I'd expect the function declaration above to lead to access violations. Instead you should declare the return value to be a Pointer and cast it to an interface reference in your Delphi code. You'll need to double check and make sure that the reference counting is handled appropriately.
Again, if you cannot modify the Delphi code, you need to make the C++ code match. A Delphi interface return value is implemented as an additional var parameter following the other parameters. So, to make your C++ function match, declare it like this:
void __stdcall GetDriver(IDriver* &retVal);
I have acquired a DLL that was created in Visual Basic from a third party vendor(Sensor DLL.dll). This DLL contains functions for talking to a sensor, and I need to call these functions from a Visual C++ program I am writing. The vendor will not provide a header file, and I do not know Visual Basic. If I had a header file this would be a 15 minute project... instead I am still struggling with it a week later. Please Help!
I am told one function (Get_Data) in the DLL is of the form:
Public Function Get_Data(ByVal Handle As String) As String
I have tried several methods for calling this Get_Data function with no success:
Method 1) the DllImport attribute
#using <mscorlib.dll>
using namespace System::Runtime::InteropServices;
namespace Sensor
{
[DllImport("Sensor DLL.dll", EntryPoint = "Get_Data", CharSet = System::Runtime::InteropServices::CharSet::Unicode)]
BSTR Get_Data(BSTR Handle);
}
//then I call the function
Sensor::Get_Data(Handle);
This method seems to be the closest I have gotten to a sloution. It compiles, but gives the following error when it runs:
An unhandled exception of type 'System.EntryPointNotFoundException' occurred
Additional information: Unable to find an entry point named 'Get_Data' in DLL 'Sensor DLL.dll'.
I have tried various datatype combinations/permutations besides BSTR including BSTR*, wchar_t, int, etc. It is possible that I missed one, but each datatype returns the same error.
Method 2) dllimport storage-class attribute
__declspec(dllimport) BSTR Get_Data(BSTR Handle);
//then I call the function
Get_Data(Handle);
This method is confusing to me because I don't specify the DLL I want to import from. I have copied the DLL to the project folder and I have added it to the project manually, so hopefully that means it can be found. When I compile the linker returns the following errors:
error LNK2028: unresolved token (0A00034F) "wchar_t * __cdecl Get_Data(wchar_t *)" (?Get_Data##$$FYAPA_WPA_W#Z) referenced in function "int __cdecl main(void)" (?main##$$HYAHXZ)
error LNK2019: unresolved external symbol "wchar_t * __cdecl Get_Data(wchar_t *)" (?Get_Data##$$FYAPA_WPA_W#Z) referenced in function "int __cdecl main(void)" (?main##$$HYAHXZ)
I suspected maybe this meant I should be using wchar_t or wchar_t* instead of BSTR, but changing to either datatype results in the same error.
Method 3) GetProcAddress
typedef BSTR (*Get_Data_Ptr)(BSTR Handle);
HINSTANCE LoadMe;
LoadMe = LoadLibraryA("Sensor DLL.dll");
if (!LoadMe)
std::cout << "\nDLL failed to load!\n";
Get_Data_Ptr LibMainGet_Data;
LibMainGet_Data = (Get_Data_Ptr)GetProcAddress(LoadMe,"Get_Data");
//then I call the function
LibMainGet_Data(Handle);
This will compile, but gives the following error when run:
An unhandled exception of type 'System.AccessViolationException' occurred
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
When I mouse over the various parts of this code in debug mode it seems that, like the first method, it was also unable to find the 'Get_Data' entry point in the DLL.
Has anyone called functions from a VB DLL using C++ when you haven't made the DLL yourself and you don't have .idl files, etc? Does anyone have a working example like this you could share?
Thanks!
A VB6 DLL is normally a COM server. You do in fact have the equivalent of a .h file, it has a type library embedded in it. Start this off with Project + Properties, Common Properties, Framework and References. Add New Reference button, Browse tab, select the DLL.
Next, View + Object Browser. You should see the generated Interop library in the list. Open the node to see what is there. You write normal managed code, like gcnew, to create the COM object and call the interface methods. You do need some minimum documentation on the available methods to have a guess at how they should be called.
I believe the missing piece is the calling convention. C++ has its own function calling convention different than VB6 (I assume VB6 since you haven't stated VB.NET explicitly). VB6 uses STDCALL convention whereas C++, depending on the vendor, uses a different calling convention termed __cdecl, which is why you see the __cdecl in the compiler error line for method #2. It assumes your external function is using that calling convention by default. Calling convention is a set of rules describing how functions call one another; specifically about how registers are used, what order parameters are delivered in, how by-value / by-reference is determined, etc.
I would suggest sticking with method #3 since method #1 is for Managed C++ which is not standard C++, and method #2 is unfamiliar to me and looks a bit ambiguous. What you want to try is declaring the function pointer typedef to use STDCALL.
typedef BSTR (__stdcall *Get_Data_Ptr)(BSTR Handle);
In the OLE/COM viewer, in order to view the COM type library in a dll/exe/... you have to open it by using "File->View TypeLib" instead of "File->Bind to File"
It sounds like the DLL isn't actually exporting a function named Get_Data. Open up a command prompt and use dumpbin to get the list of exports of the DLL, e.g.:
dumpbin /exports "Sensor DLL.dll"
(dumpbin.exe is located in VC\bin within your Visual Studio install folder, which istypically something like C:\Program Files\Microsoft Visual Studio 10.0).
Then, replace Get_Data with the actual entry point and see if you have any better luck.
A Visual basic program normally needs a runtime to execute.
If you have a COM object (implemented in VB) use the COM API to communicate with it from C++. You will have to register the COM first. Here is a thread that explains hot to do that: http://forums.devx.com/archive/index.php/t-87059.html
If you use a .NET language, use the method of Hans Passant with a reference that will create an interop dll for you. This is far much easier.
Method 1: Do not do that, if you have a COM object that you want to use from a .NET environment, reference it.
Method 2: You get errors because you lack the the .lib file to properly link to the DLL (statically dynamically linking)
Method 3: Would be a pure dynamic solution but you have to know the exact names of the methods in the DLL. These may vary according to the parameters and calling convention used. This is very similar (actually identical, I would say) to the issue you face with your Method 1 solution. The name of the method is for yure not "Get_Data" but something else. With a tool like the dependency viewer you can have a look at the exported names.
Even Method 3 with the right names is likely to fail because if it is a COM object you will need some environment called Appartment to use the COM objects. You "enter" this appartment by calling CoInitialize. This creates some magical stuff in the TLS (Thread Local Storage) to perform the COM magic. I hope this explains why your tries will be pointless if the DLL you have is happening to be a COM component, what is quite likely according to the ATL like naming we can see.
EDIT:
I forgot to say that you can also easily see what is inside the dll if it is a COM with the OLE/COM Viewer (normally if you have a compiler you will have such a tool around).
I've compiled a DLL in Visual Studio (the source code is in C++, which I barely understand). Here's a piece of Scraper.h:
struct SWin
{
char title[512];
HWND hwnd;
};
SCRAPER_API bool ScraperGetWinList(SWin winList[100]);
Now I'm trying to use the above function in my Delphi application:
type
tWin = record
title: String;
hwnd: HWND;
end;
function ScraperGetWinList(var WinList: Array of tWin): Boolean; external 'Scraper.dll';
var
myWinList: Array [1..100] of tWin;
procedure TMainForm.GetWinListButtonClick(Sender: TObject);
begin
ScraperGetWinList(myWinList);
...
The project doesn't compile, and I get the following message: The procedure entry point ScraperGetWinList could not be located in the dynamic link library: Scraper.dll.
What am I doing wrong?
From my Linux experience, I'd say that you've encountered so-called "name-mangling" issue. The entry point of your procedure is not called "ScraperGetWinList", but something like "_ZN18ScraperGetWinListEpN4SWin".
The thing is that, Unlike in C, in C++ language the name of entry point is not the same as the function name. No wonder: assume, you have a set of overloaded functions; they should have different entry points in your DLL. That's where name mangling comes into play.
The most common solution to this problem is to define interface of your library in such a way that it will use C calling convention. No name mangling will happen with the interface functions then.
Note that you don't have to write the whole library in C, you only should declare functions for them to emit C-like entry points.
Usually it's written like this:
extern "C" {
SCRAPER_API bool ScraperGetWinList(SWin winList[100]);
// More functions
}
Recompile your library and use it in Delphi without problems.
Note, that you should also adjust calling conventions (stdcall or cdecl) for them to match in your C++ header and Delphi code. However, that's best explained in another question.
Name mangling is most likely the problem. Name mangling is usually done is C++ code,
and when writing a DLL in C++ that should be used by code in an other langauge,
you should use the Extern "C" construction as Pavel Shved already suggested.
When using DLLs, especially when writtin in other languages, you should also keep
an eye on calling conventions. I suggest that you specify in both delphi and c++ to use the stdcall calling convenstion. This is the calling convention also used by the windows api, so it guarantees the best interoperatability between different compilers.
This would mean
extern "C" {
SCRAPER_API __stdcall bool ScraperGetWinList(SWin winList[100]);
}
and
function ScraperGetWinList(var WinList: Array of tWin): Boolean; external 'Scraper.dll';
But that's not all, the stdcall calling convention has an impact on the name mangling, and it would turn out to be something like _ScraperGetWinList#4 (Where 4 is the size of the parameter, where an array would have a pointer to the first element, so 4 bytes)
To confirm the correct symbols to use, I suggest Dependency Walker
( http://www.dependencywalker.com/ ) this program shows that exactly the function names are exported by the dll. Having confirmed the name to be '_ScraperGetWinList#4' then you add this in delpgi like this:
function ScraperGetWinList(var WinList: Array of tWin): Boolean; external 'Scraper.dll' name '_ScraperGetWinList#4';
Have you actually exported the entry point function in the c++ code? This really stumped me the first time I compiled a C++ dll in Visual Studio for use in a dotnet app.
For example, I needed to expose a print driver in unmanaged code so some other developers could access it in VB.net. This is what I did.
In foo.cpp:
extern "c" {
___declspec(dllexport) bool FooBar()
{
// Call some code on my cpp objects to implement foobar
}
}
Then in a file called foo.def:
LIBRARY "mylib"
EXPORTS
FooBar
AnyOtherFunctionsItExports
This is how I got it to work. I might not be doing things the best possiable way. I am a little light on C++ experience and also mainly don't work on windows.