-1

I have a dll which defines a simple functions to show a message:

library testdll;

uses SysUtils, Classes, Dialogs;

{$R *res}

procedure ShowDll;stdcall;
begin
    ShowMessage('ShowDLL testdll.dll');
end;

exports ShowDLL;
begin
end.

And my main file call this dll dynamicly using this procedure:

i defined a new type:

type
    testdll = procedure;stdcall;

Then on my button click event:

procedure TForm1.Button1Click(Sender:TObject);
var
   dllHandle: THandle; //Don't use Cardinal; it's limited to 32-bits
   test : testdll;
begin
   dllHandle := LoadLibrary('testdll.dll');
   if dllHandle <> 0 then
   begin
     @test := GetProcAddress(dllHandle,'ShowDLL');
     if Assigned(test) then
        ShowDLL
     else
        ShowMessage('Func not found');
   end
   else
      ShowMessage('dll not found');
end;

This works. But I don't know if it's possible to handle not defined functions with my dll. My purpose here is to call a function without knowing if it will be defined in my dll. So i would like the dll to tell me if the functions exists or not.

For example here i only have a ShowDLL procedure. If i call another method which does not exists it will show 'Func not found' from my main application. But i would my dll to tell me this. Is this possible? If yes, how could i achieve this pls?

EDIT: I can't modify the main function this is only a test. In my final version there will be only the dll. So exporting all functions into my main application is not possible here. That's why i want to know id the dll alone can handle it rather than doing this in my main application which i can't do.

I don't have acces to the main application to modify any code in it. I only know what are functions that will be used in this application that i will later export in my dll using exports statement. So what i try to achieve is to catch a not defined function with the dll if it's possible.

Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219
user28470
  • 419
  • 5
  • 17
  • 2
    This makes no sense. `GetProcAddress` from `kernel32.dll` already tells you if function is present in export table or not. – Free Consulting Oct 09 '14 at 08:10
  • But if the function isn't present it will return nil. I would like to return something else but from the dll, not from GetProcAdresse which is not possible folowwing David's answer – user28470 Oct 09 '14 at 08:32
  • Then roll your own table with name/pointer pairs and the magic exported function which returns function by name and *something else* when name isn't found... Is it what you want? – Free Consulting Oct 09 '14 at 10:29
  • You can't do this in the dll can you? – user28470 Oct 09 '14 at 10:32
  • The dll have to return the function not getPRocAddress. Which is different. If the dll return a function (even when it's not found) GetProcAddress will never be nil. You didn't get the question. But unfurtunatly is not possible and i got it why. Thank you anyway – user28470 Oct 09 '14 at 10:36
  • Pretty doable, if you want what I described above. I didn't understood the last comment, sorry. – Free Consulting Oct 09 '14 at 10:38
  • No problem it can't be done as i want. – user28470 Oct 09 '14 at 10:41

1 Answers1

3

Your code already demonstrates how to detect the presence of an export. Namely to call GetProcAddress and compare the result with nil.

You can reduce the amount of boiler plate code by using delay loading. This essentially lets the compiler generate the code the performs the checks. This relies on the delayed keyword.

procedure testdll; stdcall;
  external 'testdll.dll` delayed;

When you call this function, if it cannot be found, an exception is raised. Indeed this behaviour can be customised, as described in the documentation: http://docwiki.embarcadero.com/RADStudio/en/Libraries_and_Packages#Delayed_Loading

Update

In a comment to this answer you state that the executable cannot be changed. In which case, the message that you wish to avoid will be shown if the function is missing. You ask if the missing export can be handled by the DLL but that is not possible. When you call GetProcAddress, no code inside the DLL is executed. All the processing is done external to the DLL by reading its PE metadata.

The obvious conclusion is that the DLL must export the function. If the true DLL does not, put another DLL in its place. Use an interposer DLL that exports the function. Implement the function by delegating to the true DLL, if the true DLL exports the function. Otherwise do something else, whatever you please.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • But this uses the main application for catching the undefined function. Is it possible to do it with the dll? Like getting a message from the dll 'function does not exists' I'm asking this to know if i could use something like that to execute a particular code, like a default function if the called procedure/function does not exists. And i can't modify the application. That's why i'm asking if we can do this with the dll – user28470 Oct 09 '14 at 06:17
  • In my main application there only a LoadLibrary and a GetProcAddress. I can't do much more and nor less – user28470 Oct 09 '14 at 06:18
  • Why are you waiting until an answer has been written to ask the question? By announcing now that the host executable is yours, you change the question. – David Heffernan Oct 09 '14 at 06:21
  • My question wasn't clear enough and bummi marked is as duplicate so i had to edit my question. I tought it was clear enough but wassn't sorry. – user28470 Oct 09 '14 at 06:22
  • I've updated the answer based on what I think you are asking. You need to make a DLL that exports all functions. – David Heffernan Oct 09 '14 at 06:26
  • So basicly it's not possible doing this only with my dll (the function need to exist somewhere) if i get your update right. In fact in my main application they don't even handle a else statement if the functions does not exist they only check if the dll was loaded (raise excpetion ifn ot) and the call the function. They don't care if the function does not exist. So i guess i'll live with it. Thank you – user28470 Oct 09 '14 at 06:34
  • GetProcAddress just reads meta data. No code in your dll runs. Therefore if you wish GetProcAddress to return non nil you must export the function. – David Heffernan Oct 09 '14 at 06:37
  • Yeah i understand. i can't do much more with a single dll. Maybe one day it will be possible to do :P – user28470 Oct 09 '14 at 06:44