Pelles C forum

Assembly language => Assembly discussions => Topic started by: Vortex on October 01, 2023, 01:30:33 PM

Title: Calling a function from DLL at runtime
Post by: Vortex on October 01, 2023, 01:30:33 PM
Here is an example of calling the undocumented function MessageBoxTimeout at runtime.

Code: [Select]
include     Test.inc

CallFunc64  PROTO :QWORD,:QWORD,:QWORD

.data

user32  db 'user32.dll',0
MyFunc  db 'MessageBoxTimeoutA',0

message db 'This message box will be destroyed after 4 seconds.',0
caption db 'Hello',0

;   int MessageBoxTimeoutA(HWND hWnd, LPCSTR lpText,
;       LPCSTR lpCaption, UINT uType,
;       WORD wLanguageId, DWORD dwMilliseconds);

array   dq 0,OFFSET message,OFFSET caption
        dq MB_ICONWARNING,LANG_NEUTRAL,TIMEOUT

.code


main PROC PARMAREA=4*QWORD

LOCAL hMod:QWORD

    invoke  LoadLibrary,ADDR user32
    mov     hMod,rax

    invoke  GetProcAddress,rax,ADDR MyFunc

    invoke  CallFunc64,rax,6,ADDR array

    invoke  FreeLibrary,hMod

    invoke  ExitProcess,0

main ENDP


END main
Title: Re: Calling a function from DLL at runtime
Post by: John Z on October 02, 2023, 03:46:02 PM
Thanks Vortex!

Very neat, always wanted something like this, never knew it was there.
Hope I can get it to work in C.

John Z
Title: Re: Calling a function from DLL at runtime
Post by: MrBcx on October 02, 2023, 05:02:34 PM

Hope I can get it to work in C.

John Z

Hi JJ,

This will get you there.  This is the A version. 
If you want the W versions, it's only minor edits.

Code: [Select]

#include <windows.h>
#include <stdio.h>

long __stdcall MessageBoxTimeoutA (HWND, char*, char*, int, int, int);

long __stdcall MessageBoxTimeoutA (HWND hwnd,char* Txt,char* Title,int MBType,int Langid,int Milliseconds)
{
  typedef int (__stdcall *MBTYPEDEF)(HWND, char *, char *, long, int, int);
  static MBTYPEDEF MsgBoxTimeout;
  static int Result;
  HMODULE  HMOD_USER32 = LoadLibrary("user32.dll");
  MsgBoxTimeout = (MBTYPEDEF)GetProcAddress(HMOD_USER32, "MessageBoxTimeoutA");
  Result=MsgBoxTimeout(hwnd,Txt,Title,MBType,Langid,Milliseconds);
  return Result;
}

#define MBTYPE MB_YESNOCANCEL|MB_SETFOREGROUND|MB_SYSTEMMODAL|MB_ICONINFORMATION


// Demo

int main(int argc, char *argv[])
{
   printf("% d",(int)MessageBoxTimeoutA(NULL, "This works with all compilers...", "Title Goes Here", MBTYPE, 0, 4000));
   return EXIT_SUCCESS;
}

Title: Re: Calling a function from DLL at runtime
Post by: Vortex on October 02, 2023, 09:33:26 PM
Hi Kevin,

Thanks for your code. Checking the object module with Agner Fog's objconv tool, I saw that the stack was balanced after calling MessageBoxTimeoutA. This should not happen as MessageBoxTimeoutA is a STDCALL function. The code is built as 32-bit in this case.

Code: [Select]
_main   PROC NEAR
        push    4000
        push    0
        push    69699
        push    offset @1044
        push    offset @1043
        push    0           
        call    _MessageBoxTimeoutA
        add     esp, 24           
        push    eax               
        push    offset @1042       
        call    _printf           
        add     esp, 8             
        xor     eax, eax
        ret                       
_main   ENDP

The solution is inserting the __stdcall statment just before MessageBoxTimeoutA :

Code: [Select]
/*long __stdcall MessageBoxTimeoutA (HWND, char*, char*, int, int, int);*/

long __stdcall MessageBoxTimeoutA (HWND hwnd,char* Txt,char* Title,int MBType,int Langid,int Milliseconds)
{
  typedef int (__stdcall *MBTYPEDEF)(HWND, char *, char *, long, int, int);
  static MBTYPEDEF MsgBoxTimeout;
  static int Result;
  HMODULE  HMOD_USER32 = LoadLibrary("user32.dll");
  MsgBoxTimeout = (MBTYPEDEF)GetProcAddress(HMOD_USER32, "MessageBoxTimeoutA");
  Result=MsgBoxTimeout(hwnd,Txt,Title,MBType,Langid,Milliseconds);
  return Result;
}

Objconv reports now the correct output :

Code: [Select]
_main   PROC NEAR
        push    4000
        push    0   
        push    69699
        push    offset @104
        push    offset @104
        push    0   
        call    _MessageBoxTimeoutA@24  ;  no stack balance after the call to MessageBoxTimeoutA
        push    eax                   
        push    offset @1042         
        call    _printf               
        add     esp, 8               
        xor     eax, eax             
        ret                           
_main   ENDP
Title: Re: Calling a function from DLL at runtime
Post by: Vortex on October 02, 2023, 10:21:20 PM
Hello,

Pelle's Podump tool can be used to disassemble the object module :

Code: [Select]
podump.exe /DISASM MBoxTimeOut.obj
Code: [Select]
Dump of MBoxTimeOut.obj

File type: OBJ

_MessageBoxTimeoutA@24:
  [00000000] 55                     push              ebp
  [00000001] 89E5                   mov               ebp,esp
  [00000003] 53                     push              ebx
  [00000004] 56                     push              esi
  [00000005] 57                     push              edi
  [00000006] 8B5D08                 mov               ebx,dword ptr [ebp+8]
  [00000009] 8B750C                 mov               esi,dword ptr [ebp+C]
  [0000000C] 8B7D10                 mov               edi,dword ptr [ebp+10]
  [0000000F] 6800000000             push              @1025
  [00000014] FF1500000000           call              dword ptr [__imp__LoadLibraryA@4]
  [0000001A] 6800000000             push              @1027
  [0000001F] 50                     push              eax
  [00000020] FF1500000000           call              dword ptr [__imp__GetProcAddress@8]
  [00000026] A300000000             mov               dword ptr [@1023],eax
  [0000002B] FF751C                 push              dword ptr [ebp+1C]
  [0000002E] FF7518                 push              dword ptr [ebp+18]
  [00000031] FF7514                 push              dword ptr [ebp+14]
  [00000034] 57                     push              edi
  [00000035] 56                     push              esi
  [00000036] 53                     push              ebx
  [00000037] FF1500000000           call              dword ptr [@1023]
  [0000003D] A300000000             mov               dword ptr [@1024],eax
  [00000042] 5F                     pop               edi
  [00000043] 5E                     pop               esi
  [00000044] 5B                     pop               ebx
  [00000045] 89EC                   mov               esp,ebp
  [00000047] 5D                     pop               ebp
  [00000048] C21800                 ret               18
  [0000004B] 0F1F440000             nop               [eax+eax+0]

_main:
  [00000050] 68A00F0000             push              FA0
  [00000055] 6A00                   push              0
  [00000057] 6843100100             push              11043
  [0000005C] 6800000000             push              @1044
  [00000061] 6800000000             push              @1043
  [00000066] 6A00                   push              0
  [00000068] E893FFFFFF             call              00000000
  [0000006D] 50                     push              eax
  [0000006E] 6800000000             push              @1042
  [00000073] E800000000             call              _printf
  [00000078] 83C408                 add               esp,8
  [0000007B] 31C0                   xor               eax,eax
  [0000007D] C3                     ret

SUMMARY
       8 .bss
      10 .debug$F
      28 .drectve
      53 .rdata
      7E .text
Title: Re: Calling a function from DLL at runtime
Post by: Robert on October 02, 2023, 11:24:14 PM
Here is an example of calling the undocumented function MessageBoxTimeout at runtime.

Code: [Select]
include     Test.inc

CallFunc64  PROTO :QWORD,:QWORD,:QWORD

.data

user32  db 'user32.dll',0
MyFunc  db 'MessageBoxTimeoutA',0

message db 'This message box will be destroyed after 4 seconds.',0
caption db 'Hello',0

;   int MessageBoxTimeoutA(HWND hWnd, LPCSTR lpText,
;       LPCSTR lpCaption, UINT uType,
;       WORD wLanguageId, DWORD dwMilliseconds);

array   dq 0,OFFSET message,OFFSET caption
        dq MB_ICONWARNING,LANG_NEUTRAL,TIMEOUT

.code


main PROC PARMAREA=4*QWORD

LOCAL hMod:QWORD

    invoke  LoadLibrary,ADDR user32
    mov     hMod,rax

    invoke  GetProcAddress,rax,ADDR MyFunc

    invoke  CallFunc64,rax,6,ADDR array

    invoke  FreeLibrary,hMod

    invoke  ExitProcess,0

main ENDP


END main

Hi Vortex:

There is no "test.inc" file in the zip hence error

Quote
CallFunc64\Test.asm(1): fatal error: Can't open file 'Test.inc'.
Title: Re: Calling a function from DLL at runtime
Post by: Vortex on October 02, 2023, 11:32:54 PM
Hi Robert,

My apologies, it's now fixed. New upload at the top.
Title: Re: Calling a function from DLL at runtime
Post by: MrBcx on October 02, 2023, 11:51:55 PM
Erol .. thanks for the insight and correction.

I've updated the code in my post.

Title: Re: Calling a function from DLL at runtime
Post by: John Z on October 03, 2023, 11:51:20 AM
Vortex, MrBCX,

Thanks very much!  It will be very handy to now have this proc.
No longer need to thread out a dialog box and start a timer to kill it.

Very neat!'

John Z
Title: Re: Calling a function from DLL at runtime
Post by: Vortex on October 03, 2023, 07:54:01 PM
Hi John,

Your method based on dialog boxes is safer. Not easy to predict if MS is deciding one day to remove a particular undocumented function.
Title: Re: Calling a function from DLL at runtime
Post by: Pelle on October 03, 2023, 08:41:14 PM
... I can't really see the point/need for a message box that disappears after a while:
- If you have something (reasonably) important to say, don't you want confirmation it was seen?
- If it wasn't that important, why bother with a message box in the first place?

... anyway, not that important since it was an example for this example...  ::)
Title: Re: Calling a function from DLL at runtime
Post by: Vortex on October 03, 2023, 09:34:18 PM
Hi Pelle,

No worries, this is just a quick example. The LoadLibrary\GetProcAddress\Call Function method is useful to exit gracefully when a particular DLL is not everytime available.
Title: Re: Calling a function from DLL at runtime
Post by: John Z on October 04, 2023, 10:08:47 AM
No worries - I would not knowingly use any undocumented API feature in software released into the wild.
BUT
I see uses for it during development as part of a debug process.  Plus the sample C code is informative.


John Z
Title: Re: Calling a function from DLL at runtime
Post by: TimoVJL on October 04, 2023, 11:31:19 AM
What we learned, missing WINAPI leads problems.

Code: [Select]
;   int WINAPI MessageBoxTimeoutA(HWND hWnd, LPCSTR lpText,
;       LPCSTR lpCaption, UINT uType,
;       WORD wLanguageId, DWORD dwMilliseconds);
x64 don't need it, only x86
Title: Re: Calling a function from DLL at runtime
Post by: Vortex on October 04, 2023, 07:42:37 PM
Thanks to Pelle, the user32.lib import libraries are already providing the function MessageBoxTimeout :

Code: [Select]
D:\PellesC\Bin>podump.exe /EXPORTS ..\Lib\Win\user32.lib | findstr "MessageBoxTimeout"
User32.dll: MessageBoxTimeoutA (_MessageBoxTimeoutA@24)
User32.dll: MessageBoxTimeoutW (_MessageBoxTimeoutW@24)

Code: [Select]
D:\PellesC\Bin>podump.exe /EXPORTS ..\Lib\Win64\user32.lib | findstr "MessageBoxTimeout"
User32.dll: MessageBoxTimeoutA (MessageBoxTimeoutA)
User32.dll: MessageBoxTimeoutW (MessageBoxTimeoutW)
Title: Re: Calling a function from DLL at runtime
Post by: John Z on October 07, 2023, 12:08:36 PM

This will get you there.  This is the A version. 
If you want the W versions, it's only minor edits.


Thanks!  This works very well, both modal and non-modal.  Adding it to my 'Utilities.c' file.  :)

John Z
Title: Re: Calling a function from DLL at runtime
Post by: frankie on October 07, 2023, 12:33:39 PM
Adding it to my 'Utilities.c' file.  :)
Simple Tip:
If you have many 'utility' functions/procedures is better to create a static library project and put each related group of functions in a single separated file (C module). Then using the library you will link to the executable only the functions/procedures used, producing a smaller executable.
If all utility functions/procedures are coded in a single file (C module) probably the linker will put all of them, used and unused, in the executable producing a larger file.  ;)
Title: Re: Calling a function from DLL at runtime
Post by: Vortex on October 07, 2023, 07:57:11 PM
Frankie is right. It'a about the granularity concept. From Microsoft Macro Assembler's Programmer's Guide :

Quote
Granularity : The degree to which library procedures can be linked as individual blocks of code. In
Microsoft libraries, granularity is at the object-file level. If a single object file containing three
procedures is added to a library, all three procedures will be linked with the main program even if only
one of them is actually called.
Title: Re: Calling a function from DLL at runtime
Post by: jcfuller on October 08, 2023, 11:37:44 AM
I don't code much anymore and my memory is a bit faulty these days but I used this with VC++.
https://learn.microsoft.com/en-us/cpp/build/reference/gy-enable-function-level-linking?view=msvc-170

James
Title: Re: Calling a function from DLL at runtime
Post by: TimoVJL on October 08, 2023, 02:34:31 PM
I don't code much anymore and my memory is a bit faulty these days but I used this with VC++.
https://learn.microsoft.com/en-us/cpp/build/reference/gy-enable-function-level-linking?view=msvc-170

James
since ml version 12 ( msvc 2013 ) is commandline option /Gy[-] separate functions for linker
so it support COMDAT
Title: Re: Calling a function from DLL at runtime
Post by: Pelle on October 08, 2023, 02:52:40 PM
I don't code much anymore and my memory is a bit faulty these days but I used this with VC++.
https://learn.microsoft.com/en-us/cpp/build/reference/gy-enable-function-level-linking?view=msvc-170
I looked at this a long time ago, and may have forgotten some things, but IIRC the problem for me was that the COFF file format didn't really support this. It had to be implemented using somewhat fuzzy conventions.

An example: the C runtime is split up into individual files since this worked best a long time ago, when compilers/computers were slower and a MAKEFILE made sure the least amount of rebuilding were done. For me, mentally, I still like this split: one task per source file. One thing to focus on, even if the solution requires multiple functions to implement. Maybe it's just me...
Title: Re: Calling a function from DLL at runtime
Post by: frankie on October 08, 2023, 03:52:37 PM
Compilers use different approach to separate functions independently from the module they belong.
The GCC suite makes available the flag -ffunction-sections which splits the functions code in different segments in ELF format. For each function is created a subsection prepended by a period with the function name. I.e. for function:
Code: [Select]
int foo
{
    return 42;
}
Will be coded as a .text subsegment .text.foo:
Code: [Select]
Section Headers:
  [Nr] Name          Type      Addr  Off  Size ES Flg Lk Inf Al
  [ 0]               NULL      00000 0000 0000 00      0   0  0
  [ 1] .text         PROGBITS  00000 0034 0000 00  AX  0   0  1
  [ 2] .data         PROGBITS  00000 0034 0000 00  WA  0   0  1
  [ 3] .bss          NOBITS    00000 0034 0000 00  WA  0   0  1
  [ 4] .text.foo     PROGBITS  00000 0034 001c 00  AX  0   0  4
  [..]
This technique allows to easily merge all text sections back in the single text sections by having *(.text.*) spec along with *(.text) spec in built-in linker scripts.
Anyway a similar facility, named Grouped Sections, is available in MS-COFF format (available only in OBJ files), currently used for the debug sections in PellesC, where the separator used is the '$' sign:
Code: [Select]
Dump of EnumSymbols.obj
File type: OBJ
SUMMARY
      20 .data
    104B .debug$S
     3AC .debug$T
      51 .drectve
      18 .pdata
    1444 .rdata
     14A .text
      18 .xdata

MS defines Grouped sections as (https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#section-table-section-headers):
Quote
Grouped Sections (Object Only)

The "$" character (dollar sign) has a special interpretation in section names in object files.
When determining the image section that will contain the contents of an object section, the linker discards the "$" and all characters that follow it. Thus, an object section named .text$X actually contributes to the .text section in the image.
However, the characters following the "$" determine the ordering of the contributions to the image section. All contributions with the same object-section name are allocated contiguously in the image, and the blocks of contributions are sorted in lexical order by object-section name. Therefore, everything in object files with section name .text$X ends up together, after the .text$W contributions and before the .text$Y contributions.
The section name in an image file never contains a "$" character.
In analogy to the ELF format we can imagine something like:
Code: [Select]
Dump of foo.obj
File type: OBJ
SUMMARY
      20 .data
    104B .debug$S
     3AC .debug$T
      51 .drectve
      18 .pdata
    1444 .rdata
     14A .text
     15A .text.foo
      18 .xdata

Of course considering this possible doesn't mean that the implementation is easy...  :(
Title: Re: Calling a function from DLL at runtime
Post by: John Z on October 08, 2023, 04:02:26 PM
For me, mentally, I still like this split: one task per source file. One thing to focus on, even if the solution requires multiple functions to implement. Maybe it's just me...

That is what I try to maintain as well for any relatively large program.  One 'major' task per source file.  For Example if BASE64 conversions are needed then one source file for that, or export to ODS - one file.  However it makes sense that one other source file contains small routines that are used in several major task source files.  For example a character replacement routine or a left trim that is used in multiple other sources.

I didn't think about what happens with a routine being included that was written but never called....

John Z
Title: Re: Calling a function from DLL at runtime
Post by: Pelle on October 08, 2023, 05:42:22 PM
Of course considering this possible doesn't mean that the implementation is easy...  :(
Technically not hard, but there are other problems:
- how should this interact with the #pragma's code_seg, data_seg, and const_seg (I really don't know).
- many functions contain literal strings and/or static data, that will not be covered by this (referenced strings and most data are emitted at the end of the compilation, when associated function context is long lost; the data will be included by the linker, but then never referenced)
Title: Re: Calling a function from DLL at runtime
Post by: Pelle on October 08, 2023, 05:48:59 PM
However it makes sense that one other source file contains small routines that are used in several major task source files.  For example a character replacement routine or a left trim that is used in multiple other sources.
There are always multiple ways of doing things.

I have put all my truly general functions, the ones that span multiple projects, into a separate static library (and yes, each function in a separate source file). Linking with this library will pull in just what's needed.

Functions that are general for a single project (only), tend to be used in my experience (so not really a problem).
Title: Re: Calling a function from DLL at runtime
Post by: frankie on October 08, 2023, 07:03:42 PM
- how should this interact with the #pragma's code_seg, data_seg, and const_seg (I really don't know).
Well, the section flags in the Characteristics field of a section header defines the properties of the segment, executable, read-only, etc. This could help to classify it in a specific type: code, uninitialized data, read-only data, etc. This during the link identify the final standard MS-COFF segments (full list (https://learn.microsoft.com/en-us/cpp/build/reference/section-specify-section-attributes?view=msvc-170)).
When the pragma segment name is defined we have 2 options: still use the section grouping (i.e. <code_section_name>$<function_name>), or simply ignore it.

- many functions contain literal strings and/or static data, that will not be covered by this (referenced strings and most data are emitted at the end of the compilation, when associated function context is long lost; the data will be included by the linker, but then never referenced)
A solution could be to create a grouped data section also for collateral segments in the form <data_section_name>$<function_name>. This should help to determine if the segment should be included or not in the link.

Not easy, I confirm my assertion  :(, but IMO the real point is: is it worth of? If you really want to implement the MS switch /Gy then yes. Else I don't know.

What I think can be really useful is to respect the alphabetic order of the grouped sections during the code emission, because could be helpful to the sequence positioning of data in the file.
Title: Re: Calling a function from DLL at runtime
Post by: Pelle on October 08, 2023, 08:33:59 PM
but IMO the real point is: is it worth of?
I don't think so, since there are easy ways around it, but the question comes up once in a while ("since the big compilers can do it, why can't you?" yada, yada, yada...)

In some ways, a better idea would be to implement link-time optimization, but:
1) this makes much more sense for a language like C++, which will almost by definition produce many small functions (some likely identical at the machine code level), or when you build something huge like Word or Firefox.
2) this is a massive amount of work, and since C isn't C++ (yet), it's never going to happen (with Pelles C).

What I think can be really useful is to respect the alphabetic order of the grouped sections during the code emission, because could be helpful to the sequence positioning of data in the file.
If we talk about the same thing, the '$' grouping stuff requires sorting. This is (among other things) how various C runtimes collect data-blocks from different object files; use f.e. .somename$XA as the starting placeholder, .somename$XZ and the ending placeholder, and .somename$X<whatever> in different object files. When running, any data will be packed between .somename$XA and .somename$XZ (disregarding alignment, etc).

Title: Re: Calling a function from DLL at runtime
Post by: frankie on October 08, 2023, 09:01:24 PM
but IMO the real point is: is it worth of?
I don't think so, since there are easy ways around it, but the question comes up once in a while ("since the big compilers can do it, why can't you?" yada, yada, yada...)
I agree, it is very important when compiling for small memory systems, as embedded programming where the ffunction-sections switch is mandatory to keep low the memory footprint, and on very large compile jobs (C++ and other object oriented languages or large programs).
With careful structuring of source modules there should be no big problems.

What I think can be really useful is to respect the alphabetic order of the grouped sections during the code emission, because could be helpful to the sequence positioning of data in the file.
If we talk about the same thing, the '$' grouping stuff requires sorting. This is (among other things) how various C runtimes collect data-blocks from different object files; use f.e. .somename$XA as the starting placeholder, .somename$XZ and the ending placeholder, and .somename$X<whatever> in different object files. When running, any data will be packed between .somename$XA and .somename$XZ (disregarding alignment, etc).
Yes. I meant exactly that, and for that scope.  :)
Title: Re: Calling a function from DLL at runtime
Post by: Pelle on October 08, 2023, 09:21:50 PM
Yes. I meant exactly that, and for that scope.  :)
OK, good. I think this sorting have been in my linker since version 1.0, before much of it was documented. Internally it's just "the weird dollar rule", but it was essential when linking objects and libraries from Microsoft (I can't remember exactly what broke without this "feature").