The MASM Forum

General => The Workshop => Topic started by: dedndave on November 06, 2015, 05:20:09 AM

Title: LoadLibrary, GetProcAddress, FreeLibrary
Post by: dedndave on November 06, 2015, 05:20:09 AM
i have a question - can't find the answer in any MSDN document....

1) LoadLibrary
2) GetProcAddress
3) FreeLibrary

is the proc address still valid after FreeLibrary ?
same question - assuming the reference count is not 0
how would i test the answer, either way ?
Title: Re: LoadLibrary, GetProcAddress, FreeLibrary
Post by: jj2007 on November 06, 2015, 05:40:10 AM
Good question. A quick test shows that msvcrt works even after FreeLibrary.
Title: Re: LoadLibrary, GetProcAddress, FreeLibrary
Post by: ragdog on November 06, 2015, 07:26:42 AM
Quote
Good question. A quick test shows that msvcrt works even after FreeLibrary.

I understand it the handle is not longer valid.

Quote
When the reference count reaches zero, the module is unloaded from the address space of the calling process and the handle is no longer valid

I have make a quick test and Jochen has right .



Title: Re: LoadLibrary, GetProcAddress, FreeLibrary
Post by: zedd151 on November 06, 2015, 07:34:47 AM
It would'nt be very hard to write a small proggy to test whether or not
the handle would still be valid.

BUT you must make certain that no OTHER process (in
the same context as your proggy) is using that handle.

If you try to free the handle while another process is using it, it might not get freed?

That is if I understood my lessons.

Or I could be completely wrong. (Would'nt be the 1st time - lol)
Title: Re: LoadLibrary, GetProcAddress, FreeLibrary
Post by: ragdog on November 06, 2015, 08:05:34 AM
My test was wrong my second works with FreeLibrary the module after FreeLibrary is unload
and this secound call does not works.

Code: [Select]
push chr$ ("printf")
call ebx

Code: [Select]
invoke LoadLibrary,chr$ ("msvcrt.dll")
mov edi,eax
invoke GetProcAddress,eax,chr$ ("printf")
mov ebx,eax
push chr$ ("printf")
call eax
invoke FreeLibrary,edi
push chr$ ("printf")
call ebx

@ Jochen have you forgot to delete the include msvcrt?
Title: Re: LoadLibrary, GetProcAddress, FreeLibrary
Post by: TWell on November 06, 2015, 08:09:21 AM
I test msvcrt.dll and wprintf.

After FreeLibrary() function pointer was not valid anymore (crash).
Debugger shows that module unloading.

But maybe useful for undocumented API functions.
Title: Re: LoadLibrary, GetProcAddress, FreeLibrary
Post by: dedndave on November 06, 2015, 08:36:36 AM
BUT you must make certain that no OTHER process (in
the same context as your proggy) is using that handle.

the handle is unique to the current process
(the module is loaded into the address space of the current process)

the real question is.....

how do you clear out the address space used by the module to make the test   :biggrin:
Title: Re: LoadLibrary, GetProcAddress, FreeLibrary
Post by: hutch-- on November 06, 2015, 08:41:27 AM
Dave, it depends on if the library is normally loaded into memory. If its one of the main system libraries, KERNEL, USER, GDI then you can usually get away with it but with individual DLLs it would be unreliable as they would be dumped from memory in lazy write time scales.
Title: Re: LoadLibrary, GetProcAddress, FreeLibrary
Post by: dedndave on November 06, 2015, 08:42:49 AM
this takes us to the next step....

back in the old forum, we had a discussion about using LoadLibrary vs GetModuleHandle for kernel32.dll
Hutch insisted that we should use LoadLibrary and FreeLibrary
my argument was that kernel32 is always loaded (functions like ExitProcess, etc)

now, we need to know if ExitProcess clears the reference counter - lol

in other words, if i use LoadLibrary to get functions from kernel32
and - don't use FreeLibrary, in order to insure the proc addresses remain valid
will ExitProcess perform a proper clean-up, or do i have a memory leak ?
Title: Re: LoadLibrary, GetProcAddress, FreeLibrary
Post by: hutch-- on November 06, 2015, 08:49:20 AM
With the system libraries you can LoadLibrary(), GetProcAddress() then immediately call FreeLibrary() which is safe as the system library is still in memory, GetModuleHandle will do it as well without changing the reference counter but an old warning still applies, when Microsoft upgrade OS versions they only have their own documentation as reference so you may get a nasty surprise if you call a function address this way in a later OS version or after an upgrade. (Having been bitten a number of times with this problem, I err on the side of caution).  :biggrin:
Title: Re: LoadLibrary, GetProcAddress, FreeLibrary
Post by: nidud on November 06, 2015, 08:50:49 AM
deleted
Title: Re: LoadLibrary, GetProcAddress, FreeLibrary
Post by: hutch-- on November 06, 2015, 09:06:36 AM
Like this.

Code: [Select]
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    .data?
      pMessageBox dd ?

    .data
      titl db "Msgbox Call",0
      tmsg db "Howdy from the MessageBox address",0

    .code

start:
   
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    call main

    exit

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc


    LOCAL pUser :DWORD

    fn LoadLibrary,"user32.dll"
    mov pUser, eax

    fn GetProcAddress,pUser,"MessageBoxA"
    mov pMessageBox, eax

    fn FreeLibrary, pUser

    push 0
    push OFFSET titl
    push OFFSET tmsg
    push 0
    call pMessageBox

    ret

main endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

end start
Title: Re: LoadLibrary, GetProcAddress, FreeLibrary
Post by: Zen on November 06, 2015, 09:32:41 AM
Raymond Chen has a number of blog entries that are ALMOST relevant to this question,...:bgrin:
...Here's one of them that seems to answer your question: What is the point of FreeLibraryAndExitThread? (http://blogs.msdn.com/b/oldnewthing/archive/2013/11/05/10463645.aspx)
This one is even MORE OBTUSE: Why can't I use the linker to delay-load a function from kernel32? (http://blogs.msdn.com/b/oldnewthing/archive/2010/02/01/9956102.aspx)
...And, if you want to know everything about LoadLibrary, FreeLibrary that nobody realistically cares about: Why are DLLs unloaded in the "wrong" order? (http://blogs.msdn.com/b/oldnewthing/archive/2005/05/23/421024.aspx)
Title: Re: LoadLibrary, GetProcAddress, FreeLibrary
Post by: nidud on November 06, 2015, 09:39:17 AM
deleted
Title: Re: LoadLibrary, GetProcAddress, FreeLibrary
Post by: sinsi on November 06, 2015, 10:11:51 AM
Use FreeLibrary more than once to make sure the reference count is 0 and run hutch's code. The degugger gives me
Code: [Select]
<Unloaded_user32.dll>+0x6fd1e:
7669fd1e ??              ???
Title: Re: LoadLibrary, GetProcAddress, FreeLibrary
Post by: dedndave on November 07, 2015, 04:05:40 AM
my current solution is to use this code
i am considering getting rid of the FreeLibrary call, and letting ExitProcess perform the clean-up
i have to test that strategy on a variety of OS's, though

Code: [Select]
    INVOKE  GetModuleHandleA,offset __szKernel32
    .if eax
        push    0                                   ;do not free the library handle
    .else
        INVOKE  LoadLibraryA,offset __szKernel32
        push    eax                                 ;free the library handle if non-zero
    .endif

    .if eax
        ;get proc addresses, here
    .endif

    pop     eax
    .if eax
        INVOKE  FreeLibrary,eax
    .endif
Title: Re: LoadLibrary, GetProcAddress, FreeLibrary
Post by: jj2007 on November 07, 2015, 05:03:15 AM
i am considering getting rid of the FreeLibrary call, and letting ExitProcess perform the clean-up

Should work, but I still lack a good reference which types of resources (memory, gdi objects, bitmaps, DLLs, ...) are cleaned up by ExitProcess, and which aren't. Documentation is vague and sparse :(
Title: Re: LoadLibrary, GetProcAddress, FreeLibrary
Post by: dedndave on November 07, 2015, 05:08:09 AM
it would seem logical, because the process memory is released
but - i need to devise a test of some sort to see if it works on win95, 98, 2K.....
Title: Re: LoadLibrary, GetProcAddress, FreeLibrary
Post by: TouEnMasm on November 07, 2015, 07:20:00 PM
It seems that many anwer are here:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms684232(v=vs.85).aspx
Title: Re: LoadLibrary, GetProcAddress, FreeLibrary
Post by: jj2007 on November 07, 2015, 07:46:31 PM
It seems that many anwer are here:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms684232(v=vs.85).aspx

Explain where exactly these pages on "Module Information" elaborate which types of resources (memory, gdi objects, bitmaps, DLLs, ...) are cleaned up by ExitProcess, and which aren't.

Simple examples:
Quote
Because Win32 is based on Win16 there are a lot of Win16 legacy APIs that deal with window messages and the clipboard that do in fact expect HBITMAP's to be usable from multiple processes

Quote
resources managed by the Windows window manager, USER and GDI objects, that represent window elements (like windows and menus) and graphics constructs (like pens, brushes and drawing surfaces). Just like for the other resources I’ve discussed in previous posts, exhausting the various USER and GDI resource limits can lead to unpredictable behavior, including application failures and an unusable system

Released by ExitProcess, yes or no?
Title: Re: LoadLibrary, GetProcAddress, FreeLibrary
Post by: hutch-- on November 07, 2015, 07:53:14 PM
I think you can reasonably assume the ExitProcess() does what its name says, exits a process and that entails dumping all of what was loaded when it was running. The reason to use FreeLibrary() apart from the documentation recommendation is to make the exit tidy and fast. I am yet to see what the gain is in omitting FreeLibrary() when its only a simple API call.
Title: Re: LoadLibrary, GetProcAddress, FreeLibrary
Post by: sinsi on November 07, 2015, 08:03:30 PM
Fairly straightforward  :badgrin:
Quote from: MSDN
Exiting a process causes the following:

    All of the threads in the process, except the calling thread, terminate their execution without receiving a DLL_THREAD_DETACH notification.
    The states of all of the threads terminated in step 1 become signaled.
    The entry-point functions of all loaded dynamic-link libraries (DLLs) are called with DLL_PROCESS_DETACH.
    After all attached DLLs have executed any process termination code, the ExitProcess function terminates the current process, including the calling thread.
    The state of the calling thread becomes signaled.
    All of the object handles opened by the process are closed.
    The termination status of the process changes from STILL_ACTIVE to the exit value of the process.
    The state of the process object becomes signaled, satisfying any threads that had been waiting for the process to terminate.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682658%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
Title: Re: LoadLibrary, GetProcAddress, FreeLibrary
Post by: jj2007 on November 07, 2015, 09:27:01 PM
Hutch, Sinsi,

Thanks. In my own proggies, Dll & Declare (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1017) perform the FreeLibrary; perhaps it's not needed... OTOH, I never indulge in DeleteObject orgies in a WM_DESTROY handler, although you may find such stuff in Windows programming tutorials.

Below a small collection of related sources.

The Old New Thing: Quick overview of how processes exit on Windows XP (http://blogs.msdn.com/b/oldnewthing/archive/2007/05/03/2383346.aspx)
3 May 2007
The kernel will close all your open handles to kernel objects. Any memory you allocated will be freed automatically when the process's address space is torn down.

ExitProcess function (https://msdn.microsoft.com/en-us/library/windows/desktop/ms682658%28v=vs.85%29.aspx)
6. All of the object handles opened by the process are closed.

Terminating a process (https://msdn.microsoft.com/en-us/library/windows/desktop/ms686722%28v=vs.85%29.aspx) has the following results:
    Any remaining threads in the process are marked for termination.
    Any resources allocated by the process are freed.
    All kernel objects are closed.
    The process code is removed from memory.
    The process exit code is set.
    The process object is signaled.

While open handles to kernel objects are closed automatically when a process terminates, the objects themselves exist until all open handles to them are closed. Therefore, an object will remain valid after a process that is using it terminates if another process has an open handle to it.


CodeGuru Alexey B (http://forums.codeguru.com/showthread.php?198945-what-happens-during-ExitProcess-%28in-threads-stopping-static-objects-dll-unloading%29)
Regardless of how the process terminates, the system guarantees that all allocated memory, all User and GDI objects are freed, all open files are closed and the usage count on all kernel objects is decremented.

Mark Russinovich's Blog: Pushing the Limits of Windows: USER and GDI Objects (http://blogs.technet.com/b/markrussinovich/archive/2010/02/24/3315174.aspx)

User Objects
With the fundamental concepts in hand, let's turn our attention first to USER objects. USER objects get their name from the fact that they represent user interface elements like desktops, windows, menus, cursors, icons, and accelerator tables (menu keyboard shortcuts). Despite the fact that USER objects are associated with a specific desktop, they must be accessible from all the desktops of a session, for example to allow a process on one desktop to register for a hotkey that can be entered on any of them. For that reason, the window manager assigns USER object identifiers that are scoped to a window station.

A basic limitation imposed by the window manager is that no process can create more than 10,000 USER objects. That limitation attempts to prevent a single process from exhausting the resources associated with USER objects, either because it’s programmed with algorithms that can create excessive number of objects or because it leaks objects by allocating them and not deleting them when it's through using them. You can easily verify this limit by running the Sysinternals Testlimit utility with the –u switch, which directs Testlimit to create as many USER objects as it can


Debugging a GDI Resource Leak (http://blogs.msdn.com/b/dsui_team/archive/2013/04/23/debugging-a-gdi-resource-leak.aspx)

 --Definitions--

GDI Objects are resources that are managed by GDI32.DLL on behalf of an application. Some of the most common types of GDI objects are Device Contexts (DCs), Bitmaps, Brushes, Fonts, Metafiles, Pens, and Regions.  GDI Objects are stored in Kernel Memory (specifically the Paged Pool or Session Pool portions of kernel memory – more on this later).

GDI Handles are unique identifiers of a GDI Object.  Each GDI Object can have only one handle.  Each GDI Handle is process-specific (cannot be used by other processes).

The GDI Handle Table is a table (array) of GDI entries.  Each entry contains 32-bits of information about a GDI object, including the handle, the type of the object (i.e. bitmap, DC, pen, font, etc.), the process for which that handle is valid, and a pointer to the actual GDI object in Kernel Memory. This table exists in User Memory.
Title: Re: LoadLibrary, GetProcAddress, FreeLibrary
Post by: dedndave on November 07, 2015, 10:11:45 PM
and, yet, it's not hard to get a memory leak
seems to me that everything documented is not always closed
and, it is likely to be an OS version sensitive issue


I am yet to see what the gain is in omitting FreeLibrary() when its only a simple API call.

well - i write a library function that gets the proc address for some function the first time it's used
i can provide a special exit clean-up routine, but there's no guarantee that the user calls it before exit

let me cite a specific example
GlobalMemoryStatusEx is not supported by earlier OS versions
so - the library function that calls it tries to initialize the address via GetProcAddress
this is better than calling it directly, causing it to crash on older OS's
in the event that it is not supported, the routine can fall back to GlobalMemoryStatus (no Ex)

however, if i have to use LoadLibrary to ensure that Kernel32.dll is loaded,
i have incremented the reference count on that module

when it comes time to exit, the user must call a library function to decrement the count (FreeLibrary call)
if the user omits that call - what happens ?
it would be nice to eliminate that requirement by some sort of trickery
well - as we've discussed before, GetModuleHandle does not increment the reference count
but, Hutch claims it may not be safe to assume that Kernel32 is always loaded
Title: Re: LoadLibrary, GetProcAddress, FreeLibrary
Post by: hutch-- on November 08, 2015, 12:41:43 AM
> but, Hutch claims it may not be safe to assume that Kernel32 is always loaded

No, I have made the point that you risk unreliable results in other OS versions if you don't clean up correctly. If you load a library, you free it after, whether the procedure exists or not, it really that simple.

In sequence,

LoadLibrary()         ; load the library address
GetProcAddress(), ; whoops, the function does not exist
FreeLibrary()          ; you have still loaded the library.

Try this.

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    .data?
      pMessageBox dd ?
      pDudFunction dd ?

    .data
      titl db "Msgbox Call",0
      tmsg db "Howdy from the MessageBox address",0

    .code

start:
   
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    call main

    exit

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    LOCAL pKernel :DWORD
    LOCAL pUser   :DWORD

    fn LoadLibrary,"user32.dll"
    mov pUser, eax

    fn GetProcAddress,pUser,"MessageBoxA"
    mov pMessageBox, eax

    fn FreeLibrary, pUser

    push 0
    push OFFSET titl
    push OFFSET tmsg
    push 0
    call pMessageBox

    fn LoadLibrary,"kernel32.dll"
    mov pKernel, eax
    fn GetProcAddress,pKernel,"DudFunction"
    .if eax == 0
      fn MessageBox,0,"Sorry Cannot find that function",str$(eax),MB_OK
    .endif

    fn FreeLibrary, pKernel
  ; ----------------------------------------------------
  ; non zero means the FreeLibrary call worked correctly
  ; ----------------------------------------------------
    fn MessageBox,0,str$(eax),"FreeLibrary return value",MB_OK

    ret

main endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

end start
Title: Re: LoadLibrary, GetProcAddress, FreeLibrary
Post by: nidud on November 08, 2015, 01:22:08 AM
deleted
Title: Re: LoadLibrary, GetProcAddress, FreeLibrary
Post by: TWell on November 08, 2015, 02:07:24 AM
Dilemma
If someone use GetProcAddress , kernel32.dll is already loaded ;)
So other functions from kernel32.dll are available too? GetModuleHandleA is enough?
Title: Re: LoadLibrary, GetProcAddress, FreeLibrary
Post by: jj2007 on November 08, 2015, 02:31:39 AM
Dilemma
If someone use GetProcAddress , kernel32.dll is already loaded ;)
So other functions from kernel32.dll are available too? GetModuleHandleA is enough?

Who knows?

Code: [Select]
include \masm32\include\masm32rt.inc

.code
start:
  mov esi, rv(GetProcAddress, rv(GetModuleHandle, "Kernel32"), "CreateFileA")
  print LastError$()
  inkey hex$(esi)
  exit

end start
Title: Re: LoadLibrary, GetProcAddress, FreeLibrary
Post by: Adamanteus on November 08, 2015, 03:12:39 AM
 The imported libraries in exe header, makes library loaded during program execution - so need count also this.
Title: Re: LoadLibrary, GetProcAddress, FreeLibrary
Post by: nidud on November 08, 2015, 03:27:15 AM
deleted
Title: Re: LoadLibrary, GetProcAddress, FreeLibrary
Post by: dedndave on November 08, 2015, 09:35:27 PM
i think this is the code i want to use - no FreeLibrary call until exit
now, to devise a test to see if there's a leak in the event they don't clean-up   :redface:

Code: [Select]
    INVOKE  GetModuleHandleA,offset __szKernel32
    .if !eax
        INVOKE  LoadLibraryA,offset __szKernel32
        mov     __hKernel32Free,eax
    .endif

    .if eax
        ;get proc addresses, here
    .else
        dec     eax
        ;set proc address pointers to -1, signifying initialized, unsupported
    .endif
Title: Re: LoadLibrary, GetProcAddress, FreeLibrary
Post by: TouEnMasm on November 09, 2015, 05:22:34 AM

The GetModuleHandle retrieve the loaded module without the loadlibrary.
The getprocadress work.
You use that at your own risk,because the getprocadress failed if the module is unloaded by the module
using it.
This is shown by a test dll loaded only once.
If there is a poor chance to unload the kernel32.dll,it is not the same for other.