Author Topic: Functions exported by ordinals  (Read 4807 times)

Vortex

  • Moderator
  • Member
  • *****
  • Posts: 1704
Functions exported by ordinals
« on: June 07, 2014, 07:07:01 PM »
Here is a quick example :

Code: [Select]
#include <windows.h>
#include <stdio.h>

int main(int argc,char *argv[])

{
HMODULE hModule;

// define the function pointer to call the function #2

int __stdcall (*Sum)(int,int);

hModule=LoadLibrary("DllDemo.dll");

// Get the address of the function identified by ordinal number 2

Sum=(void *)GetProcAddress(hModule,MAKEINTRESOURCE(2));

// Simple test

printf("90 + 10 = %d",Sum(90,10));

FreeLibrary(hModule);

return 0;
}

DllDemo.def :

Code: [Select]
LIBRARY DllDemo
EXPORTS
Difference @1 NONAME
Sum @2 NONAME
Multiply @3 NONAME
Square @4 NONAME

Gunther

  • Member
  • *****
  • Posts: 3515
  • Forgive your enemies, but never forget their names
Re: Functions exported by ordinals
« Reply #1 on: June 07, 2014, 08:19:30 PM »
Thank you Erol for the instructive example. Will that work with other compilers, too?

Gunther

Get your facts first, and then you can distort them.

Vortex

  • Moderator
  • Member
  • *****
  • Posts: 1704
Re: Functions exported by ordinals
« Reply #2 on: June 07, 2014, 08:54:32 PM »
Hi Gunther,

Second version built with Microsoft Visual C++ Toolkit 2003 and Server 2003 R2 PSDK. The only difference is the declaration of the function pointer :

Code: [Select]
int (__stdcall *Sum)(int,int);
« Last Edit: June 08, 2014, 02:37:33 AM by Vortex »

Gunther

  • Member
  • *****
  • Posts: 3515
  • Forgive your enemies, but never forget their names
Re: Functions exported by ordinals
« Reply #3 on: June 07, 2014, 09:21:23 PM »
 :t Is clear now.

Gunther
Get your facts first, and then you can distort them.

MichaelW

  • Global Moderator
  • Member
  • *****
  • Posts: 1209
Re: Functions exported by ordinals
« Reply #4 on: June 07, 2014, 09:41:10 PM »
After changing the function declaration and renaming dllmain.c to dlldemo.c, and building with the VC++ Toolkit 2003 compiler and this batch file:
Code: [Select]
set PATH=C:\Program Files\Microsoft Visual C++ Toolkit 2003\bin;%PATH%

set INCLUDE=C:\Program Files\Microsoft Platform SDK\include;C:\Program Files\Microsoft Visual C++ Toolkit 2003\include;%INCLUDE%

set LIB=C:\Program Files\Microsoft Platform SDK\lib;C:\Program Files\Microsoft Visual C++ Toolkit 2003\lib;C:\masm32\lib;%LIB%

cl /W3 /FA /c dlldemo.c

pause

link /DLL /DEF:dlldemo.def dlldemo.obj

pause

cl /W3 /FA CallByOrdinal.c DllDemo.lib

pause

The assembly output shows that the exported functions are using cdecl:
Code: [Select]
; Listing generated by Microsoft (R) Optimizing Compiler Version 13.10.3077

TITLE dlldemo.c
.386P
include listing.inc
if @Version gt 510
.model FLAT
else
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
_DATA SEGMENT DWORD USE32 PUBLIC 'DATA'
_DATA ENDS
CONST SEGMENT DWORD USE32 PUBLIC 'CONST'
CONST ENDS
_BSS SEGMENT DWORD USE32 PUBLIC 'BSS'
_BSS ENDS
$$SYMBOLS SEGMENT BYTE USE32 'DEBSYM'
$$SYMBOLS ENDS
_TLS SEGMENT DWORD USE32 PUBLIC 'TLS'
_TLS ENDS
FLAT GROUP _DATA, CONST, _BSS
ASSUME CS: FLAT, DS: FLAT, SS: FLAT
endif

INCLUDELIB LIBC
INCLUDELIB OLDNAMES

PUBLIC _DllMain@12
; Function compile flags: /Odt
_TEXT SEGMENT
_hInstDLL$ = 8 ; size = 4
_fdwReason$ = 12 ; size = 4
_lpvReserved$ = 16 ; size = 4
_DllMain@12 PROC NEAR
; File c:\program files\microsoft visual c++ toolkit 2003\my\vortex\callbyordinal\dlldemo.c
; Line 5
push ebp
mov ebp, esp
; Line 6
mov eax, 1
; Line 7
pop ebp
ret 12 ; 0000000cH
_DllMain@12 ENDP
_TEXT ENDS
PUBLIC _Sum
; Function compile flags: /Odt
_TEXT SEGMENT
_a$ = 8 ; size = 4
_b$ = 12 ; size = 4
_Sum PROC NEAR
; Line 10
push ebp
mov ebp, esp
; Line 11
mov eax, DWORD PTR _a$[ebp]
add eax, DWORD PTR _b$[ebp]
; Line 12
pop ebp
ret 0
_Sum ENDP
_TEXT ENDS
PUBLIC _Difference
; Function compile flags: /Odt
_TEXT SEGMENT
_a$ = 8 ; size = 4
_b$ = 12 ; size = 4
_Difference PROC NEAR
; Line 15
push ebp
mov ebp, esp
; Line 16
mov eax, DWORD PTR _a$[ebp]
sub eax, DWORD PTR _b$[ebp]
; Line 17
pop ebp
ret 0
_Difference ENDP
_TEXT ENDS
PUBLIC _Multiply
; Function compile flags: /Odt
_TEXT SEGMENT
_a$ = 8 ; size = 4
_b$ = 12 ; size = 4
_Multiply PROC NEAR
; Line 20
push ebp
mov ebp, esp
; Line 21
mov eax, DWORD PTR _a$[ebp]
imul eax, DWORD PTR _b$[ebp]
; Line 22
pop ebp
ret 0
_Multiply ENDP
_TEXT ENDS
PUBLIC _Square
; Function compile flags: /Odt
_TEXT SEGMENT
_a$ = 8 ; size = 4
_Square PROC NEAR
; Line 25
push ebp
mov ebp, esp
; Line 26
mov eax, DWORD PTR _a$[ebp]
imul eax, DWORD PTR _a$[ebp]
; Line 27
pop ebp
ret 0
_Square ENDP
_TEXT ENDS
PUBLIC _func
; Function compile flags: /Odt
_TEXT SEGMENT
_a$ = 8 ; size = 4
_b$ = 12 ; size = 4
_func PROC NEAR
; Line 30
push ebp
mov ebp, esp
; Line 31
mov eax, DWORD PTR _a$[ebp]
mov ecx, DWORD PTR _b$[ebp]
lea eax, DWORD PTR [ecx+eax*2]
; Line 32
pop ebp
ret 0
_func ENDP
_TEXT ENDS
END

Is there a way to link with the import library and call a function by ordinal, without GetProcAddress?
Well Microsoft, here’s another nice mess you’ve gotten us into.

jj2007

  • Member
  • *****
  • Posts: 7558
  • Assembler is fun ;-)
    • MasmBasic
Re: Functions exported by ordinals
« Reply #5 on: June 08, 2014, 12:46:56 AM »
Nice example, Erol :t

Here is the assembler equivalent - requires version 7 June or later ;)

include \masm32\MasmBasic\MasmBasic.inc
  Init
  Dll "DllDemo.dll"
  Declare #2=TheSum, 2
  Inkey Str$("90+10=%i", TheSum(90, 10))
  Exit
end start


(actually, when trying this, it choked; the VB style ordinal option has been included a long time ago, but I've never used it, and a regression crept in :(... but now it works)

Note you can use any alias name, like MySum etc; if you try TheSum(90, 10, 123) or The Sum(90), the macro will throw an assembly time error message explaining that TheSum expects exactly 2 parameters.

The assembly output shows that the exported functions are using cdecl
The DemoDll.dll in Erol's attachment uses stdcall. If it was cdecl, the syntax above would change to Declare #2=TheSum, C:2

Vortex

  • Moderator
  • Member
  • *****
  • Posts: 1704
Re: Functions exported by ordinals
« Reply #6 on: June 08, 2014, 02:36:47 AM »
Hi Jochen,

Thanks for your kind words. By the way, my fault was not specify the correct calling convention __stdcall. I corrected this:

Code: [Select]
#ifndef WINAPI
#define WINAPI  __stdcall
#endif
.
.
.
int WINAPI Sum(int a, int b)
{
    return a+b;
}

No need of GetProcAddress now :

Code: [Select]
extern int __stdcall Sum(int x,int y);

int main(int argc,char *argv[])

{
printf("90 + 10 = %d",Sum(90,10));

return 0;
}

New upload at the top.