IonicWind Software

Aurora Compiler => Software Projects => Topic started by: sapero on January 10, 2007, 05:27:07 AM

Title: Dll2lib
Post by: sapero on January 10, 2007, 05:27:07 AM
Here it is! A tool to convert simple dll's into static library.
This is the first version, so all here is simple: the user interface has all controls on one page, you are able to access only named exports, and the dll is notified only with process attach/detach.
TLS initialization is not yet supported, module functions will always fail (GetModuleHandle...).
The dll is loaded to memory not as dll, but as code+data (using the MemoryModule loader with small modifications to operate on HMODULE instead MEMORYMODULE*)

Note: every converted dll you must manually initialize and deinitialize by single call to the loader. Every converted dll has its own (un)loader.
You can find a example usage for dx3d9r.dll with landscape.src modification.

Have fun! ;D

(http://img226.imageshack.us/img226/2473/dll2libvz6.th.jpg) (http://img226.imageshack.us/my.php?image=dll2libvz6.jpg)

edit: version 2.0.0.2 supports names up to 16320 characters
Title: Re: Dll2lib
Post by: srvaldez on January 10, 2007, 06:40:15 AM
Thank you  :)
Title: Re: Dll2lib
Post by: Steven Picard on January 10, 2007, 07:38:01 AM
Once again you have proven how amazing your programming skills are!
Title: Re: Dll2lib
Post by: ExMember001 on January 10, 2007, 11:24:10 AM
looks like a great tool ;)
will give this a go as soon as i have time !
Title: Re: Dll2lib
Post by: Shannara on January 10, 2007, 12:09:39 PM
sapero -> check pm please.
Title: Re: Dll2lib
Post by: J B Wood (Zumwalt) on February 06, 2007, 03:43:19 PM
Doesn't work on rakknet.dll, get ahold of that and try it with your application, problem is, there names are VERY LONG, and you have a character limit for length of name of the exported items.
Title: Re: Dll2lib
Post by: sapero on February 07, 2007, 05:00:51 AM
I've uploaded second version that supports names up to 16320 characters (previous limit was 260). I do not belive this is not enough ;)
The raknet has been converted ok,and the simple main() with loader only ran successfully.

// todo: undecorate names
Title: Re: Dll2lib
Post by: J B Wood (Zumwalt) on February 07, 2007, 08:36:01 AM
You rock!
Title: Re: Dll2lib
Post by: Barney on February 07, 2007, 10:10:21 AM
I bow to Sapero's mastery. Fantastic work! Thank you for sharing it with us, lesser programming mortals.

Barney
Title: Re: Dll2lib
Post by: pistol350 on February 16, 2007, 06:19:41 AM
Great !
Sapero You are the man as usual
That's a great program.
I'd be glad to see an Ebasic version. ;)
Title: Re: Dll2lib
Post by: Ionic Wind Support Team on February 16, 2007, 08:55:42 AM
The created library should work fine with Emergence.
Title: Re: Dll2lib
Post by: sapero on February 20, 2007, 03:37:46 PM
i've created a template for the (GUI) second edition. It uses tabbed property sheet, and looks better than the first version, i think so :D
The resource script was created using ResEd from Shantanu site (http://www.radasm.com/).
What do you think? It may be not correctly categorized, so please reply with any suggestions.
Title: Re: Dll2lib
Post by: Haim on February 21, 2007, 07:06:15 AM
Looks very nice.
BTW,
I looked at the dialog editor of ResEd and it looks very appealing.
How do you get the data from the dialog editor?
(controls placement and their various styles and Exstyles?)

Haim
Title: Re: Dll2lib
Post by: sapero on February 21, 2007, 07:39:17 AM
The ResEd was created for MASM, but here is a Visual Studio version (http://www.masm32.com/board/index.php?topic=6422.msg47950#msg47950).
In options menu select "C defines" as output format to easier use the script with Aurora.

Secundo: I've found a bug in MemoryModule module. Sections with IMAGE_SCN_MEM_DISCARDABLE flag can be released after calling the dll entry point.
Some packed dll's (like bass) are calculating crc32, and probably my small modification causes MemoryLoadLibrary to fail (i'm saving MEMORYMODULE pointer in dos stub).
I'll look into it, and add a option to disable releasing of discardable sections.
Title: Re: Dll2lib
Post by: Haim on February 21, 2007, 10:40:59 PM
Thanks Sapero!
Title: Re: Dll2lib
Post by: LarryMc on April 05, 2007, 04:04:19 PM
sapero
Here comes a question to display my ignorance.

What's the difference between using your utility and the make lib feature of the IDE.

Why would I want to use your program?

Again, my ignorance.

EDIT:
Okay, let's see if I'm right.
The lib made in the IDE just gives locations of functions in the DLL so you have to send people the dll with your exe.

Your program creates a static lib that loads the functions into your compiled exe so that you don't have to send a dll with your exe.


The price  that is paid is that you have to call "load" and "unload" functions to get the lib functions to work.

How close did I get?

If I'm correct then here's my next question.

If I want to create some wrappers for the functions in the first dll I do the following:
1) use your program to create a static lib of the 1st dll
2) write my wrapper functions including "open" and "close" fucntions to call the "load" and "unload" for the static lib.
3) compile my wrapper module as a dll
4) use your program to create a static lib of my dll along with the "load" and "unload" for it.
5) write my application:
   If 1st calls the "load" for my wrappers
   Then calls the "open" function in my wrappers to call the "load" for the 1st dll functions.

6) at the end of my application:
  call the "close" function in my wrappers to call the "unload" for the 1st dll functions.
  call the "unload" for my wrappers

Can you "nest" them like that.

Title: Re: Dll2lib
Post by: sapero on April 06, 2007, 07:15:57 AM
The ansver for first question:
QuoteDLL to Lib is a magical tool which can convert a DLL file into its equivalent static library file. After that, you can replace the original DLL with the static library file, rebuild your application, and distribute it without the DLL! The most exciting thing is that the conversion process DOES NOT require any source codes of the DLL! All works are done from binary to binary. DLL to Lib will rebuild programming interface identical to the functions exported by the DLL and reconstruct the necessary symbol tables, string tables and reference tables from the DLL to make a valid static library for you! Incredible?
Yes, you can nest it as well. Here is a working sample:
first dll:// dll 1

export GetOnePlusNine;

sub GetOnePlusNine(),int
{
return 1+9;
}
// compile as GetOnePlusNine.dll and convert it to static library GetOnePlusNine_m.lib

second dll that loads the first dll:// dll 2 - uses GetOnePlusNine_m.lib to wrap GetOnePlusNine()

export GetOnePlusNine_wrapped;

#use "GetOnePlusNine_m.lib" // link to static library you created from GetOnePlusNine.dll
#use "zlib.lib" // use static library

// the function we want to wrap
declare import, GetOnePlusNine(),int;

// functions to load and decompress the first dll
extern int __LoadGetOnePlusNine_dll();
extern void __UnloadGetOnePlusNine_dll();

sub GetOnePlusNine_wrapped(),int
{
__LoadGetOnePlusNine_dll();
int result = GetOnePlusNine();
__UnloadGetOnePlusNine_dll();
return result;
}
// compile as GetOnePlusNine_wrapped.dll and convert it to static library GetOnePlusNine_wrapped_m.lib

the main program:// exe main
#use "GetOnePlusNine_wrapped_m.lib"
#use "zlib.lib"
extern int __LoadGetOnePlusNine_wrapped_dll();
extern void __UnloadGetOnePlusNine_wrapped_dll();

declare import,GetOnePlusNine_wrapped(),int;

sub main(),int
{
__LoadGetOnePlusNine_wrapped_dll();

MessageBox(0, str$(GetOnePlusNine_wrapped()), "");

__UnloadGetOnePlusNine_wrapped_dll();
return 0;
}

When the exe starts, it loads the wrapped (second) dll and calls a function, where another dll is loaded (the first one) to return some value.
Title: Re: Dll2lib
Post by: LarryMc on April 06, 2007, 07:28:13 AM
Thanks a million sapero.

You're the man as usual. ;D
Title: Re: Dll2lib
Post by: pistol350 on April 06, 2007, 08:26:40 AM
Yeah!!
Very interesting.
This helps understanding better how it all works!!
Thanks Sapero  ;)
Title: Re: Dll2lib
Post by: LarryMc on April 06, 2007, 09:03:30 AM
Sapero
I'm using EBasic instead of Aurora and ran into a little problem.

I coverted your example above to EBasic.

Made the first dll and converted it to lib

Tried to compile the second and it won't compile.
It's not liking stricmp in crtdll.lib.
I looked at the 2 crtdll.libs (1 in Ebasic\libs and other in Aurora\libs.

They are not the same.

Got any idea how I can fix it?
Title: Re: Dll2lib
Post by: pistol350 on April 06, 2007, 09:12:48 AM
I was going to mention that problem  ;D
I tried to compile the seconde DLL in AURORA but failed too
There may be something wrong in the second DLL code  ???

here is what i got
Compiling...
GetOnePlusNine_wrapped.src
No Errors
Generating Exports

Linking...
Aurora Linker v1.0 Copyright ÂÃ,©2005,2006 Ionic Wind Software
Unresolved external __LoadGetOnePlusNine_dll
Error: Unresolved extern __LoadGetOnePlusNine_dll
Error: Unresolved extern __UnloadGetOnePlusNine_dll
Error(s) in linking C:\Program Files\Aurora\examples\dll to lib example\GetOnePlusNine_wrapped.dll

Cheers!
Title: Re: Dll2lib
Post by: LarryMc on April 06, 2007, 09:27:18 AM
In EBasic
If I make dll's with EBasic crtdll.lib then there is a problem with crtdll\stricmp

If I substitute Aurora crtdll.lib then there is a problem with sprintf

Any ideas how to fix?
Title: Re: Dll2lib
Post by: sapero on April 06, 2007, 05:09:33 PM
McCaughn, I remember this from IB :)
Open up your LIBS folder, find crtdll.lib and create a backup or rename it.
Run the EB GUI and from menu select Tools->Create import library. Find crtdll.dll and click ok, then ansver YES for "replace existing library" prompt.
Return to LIBS folder and rename the new crtdll.lib to _crtdll.lib, then restore the original crtdll.lib.
Now append a $use "_crtdll.lib" so it should compile now.

pistol350, in your libs folder should be the new lib file with embedded dll, try with #use "name.lib".
Optionally the lib file can be located inside your project directory, but should be added to project (menu->project->insert library).
Title: Re: Dll2lib
Post by: LarryMc on April 06, 2007, 05:11:53 PM
I wouldn't have dreamed of that in a hundred years.

Thanks
Title: Re: Dll2lib
Post by: Ionic Wind Support Team on April 06, 2007, 07:59:00 PM
And there is a reason they are different.  When I was creating IBasic Pro I wanted to be able to use static libraries created with VC++ 5.0 which prepends an underscore to all C library functions.  So I made a special version of crtdll.lib that would link against VC libs.  In order to make Emergence compatible with IBasic source code I used the same import library.

In Aurora that was no longer a priority as it already has OOP, and a more robust object set,and better COM handling, etc, etc.  So the stock crtdll.lib which contains no prepended underscores was used.  In other words I had no need to link to static libs created with VC++

Paul.
Title: Re: Dll2lib
Post by: LarryMc on April 10, 2007, 07:25:54 PM
sapero 
What I use your program to convert the 1st dll to a static lib.
I use that in a 2nd src file and create a static lib of the 2nd file

Will the 2nd static lib be a standalone lib that I can distribute to users without any other files?

Larry
Title: Re: Dll2lib
Post by: sapero on April 11, 2007, 03:56:20 AM
If the second lib has references to the first, someone will get unresolved externals. Try to rename the first one, then compile using the second lib, to check this.
If you checked the "compression" option, you need also to share zlib.lib.
Optionally you can merge two, or more libraries to one library, using the commandline ar.exe or link.exe tool, depending on library format.
Title: Re: Dll2lib
Post by: ts-soft on August 02, 2007, 09:15:22 AM
Dll2Lib doesn't work with unicode dlls in EmergencyBasic.

I think, you have to change in  MemoryGetProcAddress the second parameter, this should allways the functionname in ascii.
WinAPI GetProcAddress doesn't support Unicode, but I am not sure whether this is the mistake

greetings

Thomas
Title: Re: Dll2lib
Post by: sapero on August 02, 2007, 10:48:50 AM
I can't help without additional informations - which dll? Any code?
This tool has nothing to do with the code inside target dll, it reads only the exported names (always ascii) and creates import library wrapper that calls directry to memory, the dll code is untouched, but the IMAGE_DOS_HEADER is modified - one DWORD is used to store a pointer to internal structure.
Title: Re: Dll2lib
Post by: ts-soft on August 02, 2007, 11:07:01 AM
Sorry sapero, my mistake, i have defined UNICODE on the wrong place  :-[

It works as aspected
Title: Re: Dll2lib
Post by: LarryMc on August 29, 2008, 07:00:57 AM
Sapero
I tried to use your converter on the attached dll.
Everything convertered and when I compiled and linked it into my application it did that fine.

However, when I ran my application it crashed with the "tell MS all about it" message box.

Any ideas.

Larry
Title: Re: Dll2lib
Post by: TazMan47 on August 29, 2008, 07:54:29 AM
Hey Larry, great tool. Thanks for sharing.   ;D
Title: Re: Dll2lib
Post by: TazMan47 on August 29, 2008, 08:48:12 AM
Reference the post above. I am very sorry for changing your name to Larry. I was chatting with a friend at the time and switched your name with his. Again, I am very sorry and I hope you will forgive me.   Ken.  ;D
Title: Re: Dll2lib
Post by: sapero on August 29, 2008, 08:51:12 AM
Larry, Olly shows that this dll calls (and relies on) GetModuleFileName, searches for last '.' (_mbsrchr) and writes a NULL to that address.
GetModuleFileName fails with memory only modules, _mbsrchr returns NULL, and the code writes NULL byte to NULL pointer.
DllMain(hinstance)
{
GetModuleFileName(hinstance, bufer, ...); // set bufer to path\image323.dll
char *p = _mbsrchr(bufer, '.'); // find last '.'
*p = 0; // remove extension

You may hook the GetModuleFileName api before calling __Loadimage323_dll.
Title: Re: Dll2lib
Post by: sapero on August 29, 2008, 10:02:44 AM
Here is working exception handler: it copies dll name to the buffer provided for GetModuleFileName and resumes execution
#use "image323_m.lib"
#use "zlib.lib"
extern int __Loadimage323_dll();
extern void __Unloadimage323_dll();
#include "windows.inc"

declare import, About();

sub main(),int
{
LPTOP_LEVEL_EXCEPTION_FILTER OldFilter = SetUnhandledExceptionFilter(&Loadimage323Filter);
// load the dll from memory
__Loadimage323_dll();
SetUnhandledExceptionFilter(OldFilter);

// call some functions here
About();

// finally free the dll from memory
__Unloadimage323_dll();
return 0;
}


sub Loadimage323Filter(EXCEPTION_POINTERS* ExceptionInfo),LONG
{
EXCEPTION_RECORD *rec = ExceptionInfo->ExceptionRecord;
CONTEXT *ctx = ExceptionInfo->ContextRecord;

/*
73DC9CB2     MOV     EBX,104
73DC9CB7     PUSH    EBX
73DC9CB8     LEA     EAX,[EBP+84]
73DC9CBE     PUSH    EAX
73DC9CBF     PUSH    [DWORD ESI+6C]
73DC9CC2     CALL    [<&KERNEL32.GetModuleFileNameA>]
73DC9CC8     LEA     EAX,[EBP+84]     <- resume here
73DC9CCE     PUSH    2E
73DC9CD0     PUSH    EAX
73DC9CD1     CALL    [<&msvcrt._mbsrchr>]
73DC9CD7     POP     ECX
73DC9CD8     POP     ECX
73DC9CD9     MOV     [EBP-80],EAX
73DC9CDC     MOV     [BYTE EAX],0 <- exception
*/
// copy image323.dll to [EBP+0x84]
string *pModuleName = ctx->Ebp + 0x84;
*pModuleName = "image323.dll";

// resume execution after GetModuleFileNameA
const RESUMEOFFSET = 0x73DC9CDC - 0x73DC9CC8;
ctx->Eip = rec->ExceptionAddress - RESUMEOFFSET;

// continue execution
return EXCEPTION_CONTINUE_EXECUTION;
}
Title: Re: Dll2lib
Post by: LarryMc on August 29, 2008, 10:13:54 AM
Sapero
Although this is the Aurora forum I'm trying to use this in EB.  Will the above code convert over to EB?

Larry
Title: Re: Dll2lib
Post by: sapero on August 29, 2008, 01:21:22 PM
Sure.$use "d:\\aurora\\libs\\image323_m.lib" /* change this*/

$use "zlib.lib"
declare extern __Loadimage323_dll(),int
declare extern __Unloadimage323_dll()
$include "windows.inc"

declare import, About()

main()

sub main()

LPTOP_LEVEL_EXCEPTION_FILTER OldFilter

OldFilter= SetUnhandledExceptionFilter(&Loadimage323Filter)

' load the dll from memory
__Loadimage323_dll()
SetUnhandledExceptionFilter(OldFilter)

' call some functions here
About()

' finally free the dll from memory
__Unloadimage323_dll()
return
endsub


sub Loadimage323Filter(EXCEPTION_POINTERS ExceptionInfo),LONG

pointer rec, ctx, pModuleName

rec = ExceptionInfo.ExceptionRecord
ctx = ExceptionInfo.ContextRecord
settype rec, EXCEPTION_RECORD
settype ctx, CONTEXT

' copy "image323.dll" to [EBP+0x84]
pModuleName = *ctx.Ebp + 0x84
*<STRING>pModuleName = "image323.dll"

' resume execution after GetModuleFileNameA
const RESUMEOFFSET = 0x73DC9CDC - 0x73DC9CC8
*ctx.Eip = *rec.ExceptionAddress - RESUMEOFFSET

' continue execution
return EXCEPTION_CONTINUE_EXECUTION
endsub
Title: Re: Dll2lib
Post by: LarryMc on August 29, 2008, 01:46:38 PM
Thanks again, Sapero

Larry