link from a dll to another function in another dll?

Rainer Schuetze r.sagitario at gmx.de
Mon May 2 11:29:45 PDT 2011


If you are coming from java, you are probalby used to the ideal world of 
VM programming, where everything is abstracted away from the actual 
platform you are running on.

What you are trying to do with replacing kernel32.dll pokes around in 
very lowlevel Windows specific implementation details. The complications 
are not introduced by the language, but by the DLL file layout and the 
tools available to deal with it. I have no experience using java, but I 
don't think you'll be able to do something similar with it. Even with 
C/C++, it's almost impossible without inline assembler and similar 
linker support as with D.

Coming back to your wrapper DLL, compilation should work (with symbols 
restricted to those actual needed to avoid the recent bug) with

dmd kernel32.d kernel32.def

The generated kernel32.dll is good enough to replace the original DLL 
(if it has not been loaded from the windows directory before the 
implicite DLL loading takes place). As soon as it is loaded, its' import 
dependencies will automatically load kernel33.dll. No other build steps 
required.


maarten van damme wrote:
> To avoid any confusing on my end, the files I need are
> kernel33.dll (original kernel32.dll)
> kernel33.def (So d can acces those functions)
> kernel32.def (renaming happens over here, contains a list of all 
> import-exported functions)
> kernel32.d (the code)
> 
> kernel33.def can be seen as a substitute for the import libary generated 
> by implib?
> and when you have an import library you also need a .di file to acces 
> the contents?
> 
> the compile commands are
> dmd -d kernel32 kernel32.def kernel33.def
> dmd -d kernel32.obj kernel32.def
> 
> Tomorow I can show the files (can't acces them from this laptop)
> and I'll post some snipets from the .def files ?
> 
> Can someone correct me? I'm finding d promising as language but some 
> things seem to be overly complicated to me (I'm a java guy, you have 
> .java for source, .class compiled and .jar packaged Seems way simpler xd).
> 
> 
> really apreciating your info here :D
> 2011/5/1 maarten van damme <maartenvd1994 at gmail.com 
> <mailto:maartenvd1994 at gmail.com>>
> 
>     Yes, and i have a kernel32.def for my .d file and a kernel33.def for
>     the original kernel dll. Your not confused, I am. I thought i needed
>     kerel33.def so i could acces the dll from d, isnt this the case?
> 
>     Op 1-mei-2011 22:10 schreef "Rainer Schuetze" <r.sagitario at gmx.de
>     <mailto:r.sagitario at gmx.de>> het volgende:
> 
>      > I must have completely misunderstood what you want to do. What do
>     you
>      > want to build from kernel33.def? Isn't kernel33.dll the original DLL
>      > that you want to intercept by replacing it with the compiled DLL?
>      >
>      > maarten van damme wrote:
>      >> Great, now the error in kernel32.def is resolved but it gets the
>     same
>      >> problem in kernel33.def.
>      >> here is the start of the exports from kernel33.def:
>      >> EXPORTS
>      >> _hread @1334
>      >> how can I change this to resolve that?
>      >>
>      >> 2011/5/1 Rainer Schuetze <r.sagitario at gmx.de
>     <mailto:r.sagitario at gmx.de> <mailto:r.sagitario at gmx.de
>     <mailto:r.sagitario at gmx.de>>>
>      >>
>      >> It seems you have hit another of those dreaded optlink bugs.
>      >>
>      >> With less symbols, it works if you declare the imports like this
>      >> (because of the described name mangling):
>      >>
>      >> IMPORTS
>      >> _imported_hread at 0 = kernel33._hread
>      >>
>      >> 2 more notes:
>      >> - you don't need to import kernel33.di
>      >> - you should not use "SINGLE" in the DATA statement of the def file,
>      >> it will share the memory across processes.
>      >>
>      >>
>      >>
>      >> maarten van damme wrote:
>      >>
>      >> Number overflow?
>      >> So I implemented the suggested changes (you can check them out
>      >> at http://dl.dropbox.com/u/15024434/version2.zip)
>      >>
>      >> But now I get when I compile it : "kernel32.def(738) : Error 12:
>      >> Number Overflow: (strange symbol over here)"
>      >>
>      >> I do agree I should've picked a simpler example but I think the
>      >> statisfaction will be even bigger if I were to succeed :p
>      >>
>      >> 2011/5/1 maarten van damme <maartenvd1994 at gmail.com
>     <mailto:maartenvd1994 at gmail.com>
>      >> <mailto:maartenvd1994 at gmail.com
>     <mailto:maartenvd1994 at gmail.com>> <mailto:maartenvd1994 at gmail.com
>     <mailto:maartenvd1994 at gmail.com>
>      >> <mailto:maartenvd1994 at gmail.com <mailto:maartenvd1994 at gmail.com>>>>
>      >>
>      >>
>      >> Wow, thanks for the help
>      >> The first thing I did was in the .di file adding
>      >> extern(windows){ .... }
>      >> and now compiling doesn't give errors and when examining with
>      >> dllexp
>      >> I can see that it exports the same functions as the real
>      >> kernel32.dll :D
>      >>
>      >> Now I'm going to implement all other suggested changes,
>      >> thanks a lot
>      >>
>      >>
>      >> 2011/4/30 Rainer Schuetze <r.sagitario at gmx.de
>     <mailto:r.sagitario at gmx.de>
>      >> <mailto:r.sagitario at gmx.de <mailto:r.sagitario at gmx.de>>
>      >> <mailto:r.sagitario at gmx.de <mailto:r.sagitario at gmx.de>
>     <mailto:r.sagitario at gmx.de <mailto:r.sagitario at gmx.de>>>>
>      >>
>      >>
>      >> I'm not sure your wrapping will work with kernel32.dll,
>      >> but in
>      >> general here are a few tips:
>      >>
>      >> - most functions in the windows API use the __stdcall calling
>      >> convention in C/C++, which translates to D as
>      >> "extern(Windows)"
>      >>
>      >> - this will usually add the number of bytes passed on the
>      >> stack
>      >> as a "@NN" postfix to the function name. This postfix
>      >> does not
>      >> exist in kernel32.dll, but in the import library kernel32.lib
>      >> that you find in the dmd lib folder. Maybe you can use the
>      >> standard import library, or use the translation shown below..
>      >>
>      >> - as the exported function and the function you want to
>      >> chain to
>      >> have identical names, you have to change at least one of
>      >> these
>      >> and modify them in some build step. I'd suggest to do this in
>      >> the def file:
>      >>
>      >> The symbols in the d-source file containing:
>      >>
>      >> ----
>      >> extern(Windows) HANDLE imported_GetCurrentProcess();
>      >>
>      >> export extern(Windows) HANDLE internal_GetCurrentProcess()
>      >> {
>      >> return imported_GetCurrentProcess();
>      >> }
>      >> ----
>      >>
>      >> can be mapped to other symbols in the def file:
>      >>
>      >> ----
>      >> EXPORTS
>      >> GetCurrentProcess = internal_GetCurrentProcess
>      >>
>      >> IMPORTS
>      >> imported_GetCurrentProcess = kernel33.GetCurrentProcess
>      >> ----
>      >>
>      >> - if you don't know the number of arguments, you should
>      >> not call
>      >> the wrapped function, as this will change the callstack.
>      >> Instead, you should just jump to it:
>      >>
>      >> void internal_hread()
>      >> {
>      >> asm
>      >> {
>      >> naked;
>      >> jmp imported_hread;
>      >> }
>      >> }
>      >>
>      >> I haven't tried all that, though, so there might be some
>      >> mistakes...
>      >>
>      >> Rainer
>      >>
>      >>
>      >>
>      >> Denis Koroskin wrote:
>      >>
>      >> On Sat, 30 Apr 2011 13:47:53 +0400, maarten van damme
>      >> <maartenvd1994 at gmail.com <mailto:maartenvd1994 at gmail.com>
>      >> <mailto:maartenvd1994 at gmail.com
>     <mailto:maartenvd1994 at gmail.com>> <mailto:maartenvd1994 at gmail.com
>     <mailto:maartenvd1994 at gmail.com>
>      >> <mailto:maartenvd1994 at gmail.com <mailto:maartenvd1994 at gmail.com>>>>
>      >>
>      >> wrote:
>      >>
>      >> I've changed this, I think I'm still kinda
>      >> confused with
>      >> lib files.. They've
>      >> told me you can't do something with them without
>      >> a .di file
>      >> So I went ahead and made a kernel33.di file.. I now
>      >> import it in kernel32.d
>      >> and my declaration is
>      >> System(C){
>      >> export void * exportedfunctionblablabal(){
>      >> return exportedfunctionblablablal();
>      >> }
>      >> ....
>      >> }
>      >>
>      >> The file in the directory are:
>      >> kernel32.d :
>      >> http://dl..dropbox.com/u/15024434/d/kernel32.d
>     <http://dl.dropbox.com/u/15024434/d/kernel32.d>
>      >> kernel33.di :
>      >> http://dl.dropbox.com/u/15024434/d/kernel33.di
>      >> kernel33.lib :
>      >> http://dl.dropbox.com/u/15024434/d/kernel33.lib
>      >> kernel33.dll :
>      >> http://dl.dropbox.com/u/15024434/d/kernel33.dll
>      >>
>      >> I've tried to compile using dmd -d kernel32.d
>      >> kernel33.di kernel33.lib but
>      >> it throws errors like
>      >> "Error 42: Symbol undifined _Dkernel1336_hreadfzpV"
>      >> I have literally no clue why this is the case, can
>      >> someone help me out or
>      >> look at the files?
>      >>
>      >> 2011/4/27 maarten van damme
>      >> <maartenvd1994 at gmail.com <mailto:maartenvd1994 at gmail.com>
>     <mailto:maartenvd1994 at gmail.com <mailto:maartenvd1994 at gmail.com>>
>      >> <mailto:maartenvd1994 at gmail.com <mailto:maartenvd1994 at gmail.com>
>      >> <mailto:maartenvd1994 at gmail.com <mailto:maartenvd1994 at gmail.com>>>>
>      >>
>      >>
>      >> I'm afraid I've been a little unclear.
>      >> I've copied kernel32.dll from the windows dir,
>      >> renamed it to kernel33.dll
>      >> and generated a .lib from it using implib.
>      >> Then I've created a d file with a correct
>      >> dllmain(stolen from examples) and
>      >> between
>      >>
>      >> system(C){
>      >> export void * exportedfunctionfromkernel33.dll();
>      >> export void *
>      >> exportedfunction2fromkernel33.dll();
>      >> ....
>      >> }
>      >>
>      >> But it looks like you can't both declare a
>      >> function
>      >> from another lib and
>      >> export it at the same time.
>      >>
>      >>
>      >> In your kernel33.di, try making it extern (C) export
>      >> void*
>      >> _hread(); etc. You functions get D mangling otherwise.
>      >>
>      >> I'd also suggest you to start with a less complex
>      >> example,
>      >> e.g. export only one function, make sure it works,
>      >> then add
>      >> the rest.
>      >>
>      >> If you think your .lib files doesn't do its job, try
>      >> using
>      >> .def file instead. I find them extremely helpful, and
>      >> they
>      >> are a lot easier to edit/extend.
>      >>
>      >> Hope that helps.
>      >>
>      >>
>      >>
>      >>
> 
> 


More information about the Digitalmars-d mailing list