3

I've found a unit with functions that allow to Load a DLL directly from memory, but I don't know how can I use it..

This is the unit: http://www.delphibasics.info/home/delphibasicssnippets/udllfrommem-loadadllfrommemory

I know that the function is:

function memLoadLibrary(FileBase : Pointer) : Pointer;

But I don't know how can I use it, what is the FileBase that I need to define, etc.

Can anyone help-me?

JasonMArcher
  • 14,195
  • 22
  • 56
  • 52
paulohr
  • 576
  • 1
  • 9
  • 24

2 Answers2

4

You simply need to put the DLL into memory and pass to memLoadLibrary the pointer to the location of the DLL in memory.

For example, from a resource:

hRes := LoadResource(HInstance, 'MYRESNAME');
if hres=0 then
  RaiseLastOSError;
BaseAddress := LockResource(hRes);
if BaseAddress=nil then
  RaiseLastOSError;
lib := memLoadLibrary(BaseAddress);
.....
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • David, put DLL into memory means that I need to put the DLL in resource? – paulohr Mar 30 '12 at 17:44
  • I don't know. Could be. Why are you wanting to load from memory rather than file? – David Heffernan Mar 30 '12 at 17:46
  • What I really want is load a DLL from internet e.g. (www.mywebsite.com/mydll.dll), So, when I need to update, just upload the new DLL to the website. Undertand? Is it possible with or without this code. – paulohr Mar 30 '12 at 17:53
  • 2
    Far and away the easiest way to do that is to download from the website and same to a temporary file. Then call `LoadLibrary`. Loading from memory is not supported by MS and is a hack. It's liable to break in future Windows. But if you are set on memory loading then download to a block of memory and then call `memLoadLibrary`. – David Heffernan Mar 30 '12 at 17:55
  • So, is impossible load a DLL from internet without downloading? :/ – paulohr Mar 30 '12 at 18:00
  • That's right. You have to bring the DLL to your machine first. – David Heffernan Mar 30 '12 at 18:01
  • Wait... As I undertand your comment, Is possible download the DLL to a block of memory (in my program) and then call memLoadLibrary pointing to the block of memory? – paulohr Mar 30 '12 at 18:05
  • Yes that would work. Would you mind my asking why you don't download to a temp file and then load from there using the standard routines? – David Heffernan Mar 30 '12 at 18:06
  • Because I want to know how can I do this... I don't want to download nothing to computer, just want load.. Can you tell me about tutorials or explanations about How download a file to the block of memory in my program? – paulohr Mar 30 '12 at 18:10
  • 1
    The accepted answer here has all you need http://stackoverflow.com/questions/2184473/download-a-file-from-internet-programatically-with-an-progress-event-using-delph – David Heffernan Mar 30 '12 at 18:15
  • David, can you say if I'm correct: I download the DLL to a TMemoryStream variable, then I call memLoadLibrary pointing to TMemoryStream variable? ?? – paulohr Mar 30 '12 at 18:42
  • 1
    You use the `Memory` property of `TMemoryStream`. So you call `memLoadLibrary(MemoryStream.Memory);` – David Heffernan Mar 30 '12 at 18:44
2

Let's say you have both procedure and function in your DLL you want to load from memory to use them:

    ** GLOBAL ** (both, exe -> dll)
    type
      TTest1Proc = record
        Proc: procedure; StdCall;
        hLib: THandle;
      end;

      TTest2Func = record
        Func: function: Boolean; StdCall;
        hLib: THandle;
      end;

    ** DLL **

    procedure Test1; StdCall;
    begin
      ShowMessage('Test proc');
    end;

    function Test2: Boolean; StdCall;
    begin
      Result := True;
    end;

    exports
      Test1.
      Test2;

This is how you could load dll and use both methods (procedure and function) in your .EXE project:

    procedure Test1;
    var
      Test1Proc: TTest1Proc;
    begin
      with Test1Proc do
      begin
        hLib := LoadLibrary(PChar('DLL_PATH.dll'));
        if hLib <> 0 then
        begin
          @Proc := GetProcAddress(hLib, 'Test1');
          if Assigned(Proc) then
          try
            Proc; //will execute dll procedure Test1
          finally
            FreeLibrary(hLib);
          end
          else
          ShowMessage('Procedure not found on DLL');
        end
        else
        ShowMessage('DLL not found.');
      end;
    end;

And as function:

    function Test2: Boolean;
    var
      Test2Func: TTest2Func;
    begin
      Result := False;
      with Test2Func do
      begin
        hLib := LoadLibrary(PChar('DLL_PATH.dll'));
        if hLib <> 0 then
        begin
          @Func := GetProcAddress(hLib, 'Test2');
          if Assigned(Func) then
          try
            Result := Func; //will execute the function Test2
          finally
            FreeLibrary(hLib);
          end
          else
          ShowMessage('Function not found on DLL.');
        end
        else
        ShowMessage('DLL not found.');
      end;
    end;
  • Have another read of the question. We are not talking about LoadLibrary, rather the often discussed hack of loading modules from memory. – David Heffernan Mar 30 '12 at 17:56
  • Thanks for explaining Alexey, but, as it is written in unit, I can load the DLL without have the DLL in my HD. So, I don't need to specify the DLL Path.. right? – paulohr Mar 30 '12 at 17:56
  • You could do as David suggested to download your web DLL to a temp folder and than use the local temp path with a Loadlibrary routine like the one I've posted. – Alexey Honorio Mar 30 '12 at 18:02