Author Topic: Load DLL from memory (using RCDATA)  (Read 2686 times)

Patrice Terrier

  • Administrator
  • *****
  • Posts: 1980
    • zapsolution
Load DLL from memory (using RCDATA)
« on: December 03, 2021, 01:52:16 pm »
I have used for years this PB code to load a DLL from memory.

LoadDLLfromMemory
is able to load a DLL completely from memory, without storing it on the disk first.

This code is based on the work of Semen and Lothar posted long ago on the PowerBASIC forum.

Code: [Select]
'+--------------------------------------------------------------------------+
'|                                                                          |
'|                          (LoadDLLfromMemory)                             |
'|                                                                          |
'|                         Author Patrice TERRIER                           |
'|                         copyright(c) 2007-2014                           |
'|                           www.zapsolution.com                            |
'|                        pterrier@zapsolution.com                          |
'|                                                                          |
'+--------------------------------------------------------------------------+
'|                  Project started on : 00-06-2007 (MM-DD-YYYY)            |
'|                        Last revised : 01-02-2014 (MM-DD-YYYY)            |
'+--------------------------------------------------------------------------+

#COMPILE EXE "test.exe"
#RESOURCE "mydll.pbr"

macro const = macro

const IMAGE_ORDINAL_FLAG                = &H80000000
const IMAGE_NUMBEROF_DIRECTORY_ENTRIES  = 16
const IMAGE_NT_OPTIONAL_HDR32_MAGIC     = &H10b

const IMAGE_DOS_SIGNATURE    = &H5A4D      ' MZ
const IMAGE_OS2_SIGNATURE    = &H454E      ' NE
const IMAGE_OS2_SIGNATURE_LE = &H454C      ' LE
const IMAGE_VXD_SIGNATURE    = &H454C      ' LE
const IMAGE_NT_SIGNATURE     = &H00004550  ' PE00

const IMAGE_DIRECTORY_ENTRY_EXPORT         = 0  ' // Export Directory
const IMAGE_DIRECTORY_ENTRY_IMPORT         = 1  ' // Import Directory
const IMAGE_DIRECTORY_ENTRY_RESOURCE       = 2  ' // Resource Directory
const IMAGE_DIRECTORY_ENTRY_EXCEPTION      = 3  ' // Exception Directory
const IMAGE_DIRECTORY_ENTRY_SECURITY       = 4  ' // Security Directory
const IMAGE_DIRECTORY_ENTRY_BASERELOC      = 5  ' // Base Relocation Table
const IMAGE_DIRECTORY_ENTRY_DEBUG          = 6  ' // Debug Directory
'// IMAGE_DIRECTORY_ENTRY_COPYRIGHT        =  7   // (X86 usage)
const IMAGE_DIRECTORY_ENTRY_COPYRIGHT      =  7  ' // (X86 usage)
const IMAGE_DIRECTORY_ENTRY_ARCHITECTURE   = 7  ' // Architecture Specific Data
const IMAGE_DIRECTORY_ENTRY_GLOBALPTR      = 8  ' // RVA of GP
const IMAGE_DIRECTORY_ENTRY_TLS            = 9  ' // TLS Directory
const IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG    = 10  ' // Load Configuration Directory
const IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT   = 11  ' // Bound Import Directory in headers
const IMAGE_DIRECTORY_ENTRY_IAT            = 12  ' // Import Address Table
const IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT   = 13  ' // Delay Load Import Descriptors
const IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14  ' // COM Runtime descriptor
const IMAGE_SIZEOF_SHORT_NAME = 8

const MEM_COMMIT             = &H1000???
const PAGE_READONLY          = &H02???
const PAGE_READWRITE         = &H04???
const PAGE_EXECUTE_READ      = &H20???
const PAGE_EXECUTE_READWRITE = &H40???

const DLL_PROCESS_DETACH     = 0
const DLL_PROCESS_ATTACH     = 1
const MEM_RELEASE            = &H8000???
const RT_RCDATA              = 10

type IMAGE_EXPORT_DIRECTORY dword fill
    Characteristics       as dword
    TimeDateStamp         as dword
    MajorVersion          as word
    MinorVersion          as word
    nName                 as dword
    nBase                 as dword
    NumberOfFunctions     as dword
    NumberOfNames         as dword
    AddressOfFunctions    as dword   ' // RVA from base of image
    AddressOfNames        as dword   ' // RVA from base of image
    AddressOfNameOrdinals as dword   ' // RVA from base of image
end type

' // Size = 64 bytes
type IMAGE_DOS_HEADER byte
    e_magic    as word   ' word // Magic number
    e_cblp     as word   ' word // Bytes on last page of file
    e_cp       as word   ' word // Pages in file
    e_crlc     as word   ' word // Relocations
    e_cparhdr  as word   ' word // Size of header in paragraphs
    e_minalloc as word   ' word // Minimum extra paragraphs needed
    e_maxalloc as word   ' word // Maximum extra paragraphs needed
    e_ss       as word   ' word // Initial (relative) SS value
    e_sp       as word   ' word // Initial SP value
    e_csum     as word   ' word // Checksum
    e_ip       as word   ' word // Initial IP value
    e_cs       as word   ' word // Initial (relative) CS value
    e_lfarlc   as word   ' word // File address of relocation table
    e_ovno     as word   ' word // Overlay number
    e_res(3)   as word   ' word[4] // Reserved words
    e_oemid    as word   ' word // OEM identifier (for e_oeminfo)
    e_oeminfo  as word   ' word // OEM information; e_oemid specific
    e_res2(9)  as word   ' word[10] // Reserved words
    e_lfanew   as long   ' long // File address of new exe header
end type

type IMAGE_FILE_HEADER dword fill
    Machine              as word
    NumberOfSections     as word
    TimeDateStamp        as dword
    PointerToSymbolTable as dword
    NumberOfSymbols      as dword
    SizeOfOptionalHeader as word
    Characteristics      as word
end type

type IMAGE_DATA_DIRECTORY dword
    VirtualAddress as dword
    nSize          as dword
end type

type IMAGE_OPTIONAL_HEADER dword fill
    ' Standard fields.
    Magic                       as word
    MajorLinkerVersion          as byte
    MinorLinkerVersion          as byte
    SizeOfCode                  as dword
    SizeOfInitializedData       as dword
    SizeOfUninitializedData     as dword
    AddressOfEntryPoint         as dword
    BaseOfCode                  as dword
    BaseOfData                  as dword
    ' NT additional fields.
    ImageBase                   as dword
    SectionAlignment            as dword
    FileAlignment               as dword
    MajorOperatingSystemVersion as word
    MinorOperatingSystemVersion as word
    MajorImageVersion           as word
    MinorImageVersion           as word
    MajorSubsystemVersion       as word
    MinorSubsystemVersion       as word
    Win32VersionValue           as dword
    SizeOfImage                 as dword
    SizeOfHeaders               as dword
    CheckSum                    as dword
    Subsystem                   as word
    DllCharacteristics          as word
    SizeOfStackReserve          as dword
    SizeOfStackCommit           as dword
    SizeOfHeapReserve           as dword
    SizeOfHeapCommit            as dword
    LoaderFlags                 as dword
    NumberOfRvaAndSizes         as dword
    DataDirectory(IMAGE_NUMBEROF_DIRECTORY_ENTRIES - 1) as IMAGE_DATA_DIRECTORY
end type

type IMAGE_NT_HEADERS dword
    Signature      as dword
    FileHeader     as IMAGE_FILE_HEADER
    OptionalHeader as IMAGE_OPTIONAL_HEADER
end type

' // Size = 4 bytes
type SYSTEM_INFO_UNION_STRUCT word
    wProcessorArchitecture as word   ' word wProcessorArchitecture
    wReserved              as word   ' word wReserved
end type

' // Size = 4 bytes
union SYSTEM_INFO_UNION dword
    dwOemId as dword   ' dword dwOemId;          // Obsolete field...do not use
    SYSTEM_INFO_UNION_STRUCT
end union

' // Size = 36 bytes
type SYSTEM_INFO dword fill
    SYSTEM_INFO_UNION
    dwPageSize                  as dword   ' dwPageSize
    lpMinimumApplicationAddress as dword   ' lpMinimumApplicationAddress
    lpMaximumApplicationAddress as dword   ' lpMaximumApplicationAddress
    dwActiveProcessorMask       as dword   ' dwActiveProcessorMask
    dwNumberOfProcessors        as dword   ' dwNumberOfProcessors;
    dwProcessorType             as dword   ' dwProcessorType
    dwAllocationGranularity     as dword   ' dwAllocationGranularity
    wProcessorLevel             as word    ' wProcessorLevel
    wProcessorRevision          as word    ' wProcessorRevision
end type

union MiscUnionISH dword
    PhysicalAddress as dword   ' dword
    VirtualSize     as dword   ' dword
end union

union IMAGE_SECTION_HEADER_NAME_UNION
    Name as string * IMAGE_SIZEOF_SHORT_NAME   ' byte
    '// for compatibility wirh the PB headers
    bName(IMAGE_SIZEOF_SHORT_NAME - 1) as byte
end union

' // Size = 40 bytes
type IMAGE_SECTION_HEADER dword fill
    IMAGE_SECTION_HEADER_NAME_UNION
    Misc                 as MiscUnionISH
    VirtualAddress       as dword
    SizeOfRawData        as dword
    PointerToRawData     as dword
    PointerToRelocations as dword
    PointerToLinenumbers as dword
    NumberOfRelocations  as word
    NumberOfLinenumbers  as word
    Characteristics      as dword
end type

type IMAGE_IMPORT_BY_NAME
    Hint                   as word
    ImpName                as asciiz * 254
end type

type IMAGE_IMPORT_DESCRIPTOR
    OriginalFirstThunk     as dword
    TimeDateStamp          as dword
    ForwarderChain         as dword
    pName                  as dword
    FirstThunk             as dword
end type

type IMAGE_BASE_RELOCATION
    VirtualAddress as dword
    SizeOfBlock as dword
end type

declare sub GetSystemInfo lib "KERNEL32.DLL" ALIAS "GetSystemInfo" (byref lpSystemInfo as SYSTEM_INFO)
declare function VirtualAlloc lib "KERNEL32.DLL" ALIAS "VirtualAlloc" (byval lpAddress as dword, byval dwSize as dword, byval flAllocationType as dword, byval flProtect as dword) as dword
declare function VirtualProtect lib "KERNEL32.DLL" ALIAS "VirtualProtect" (byval lpAddress as dword, byval dwSize as dword, byval flNewProtect as dword, byref lpflOldProtect as dword) as long
declare function VirtualFree lib "KERNEL32.DLL" ALIAS "VirtualFree" (byval lpAddress as dword, byval dwSize as dword, byval dwFreeType as dword) as long
declare sub MoveMemory lib "KERNEL32.DLL" ALIAS "RtlMoveMemory" (pDestination as any, pSource as any, byval cbLength as long)
declare function GetModuleHandle lib "KERNEL32.DLL" ALIAS "GetModuleHandleA" (lpModuleName as asciiz) as dword
declare function FindResource lib "KERNEL32.DLL" ALIAS "FindResourceA" (byval hInstance as dword, lpName as asciiz, lpType as asciiz) as long
declare function SizeofResource lib "KERNEL32.DLL" ALIAS "SizeofResource" (byval hInstance as dword, byval hResInfo as dword) as long
declare function LockResource lib "KERNEL32.DLL" ALIAS "LockResource" (byval hResData as dword) as dword
declare function LoadResource lib "KERNEL32.DLL" ALIAS "LoadResource" (byval hInstance as dword, byval hResInfo as dword) as long

declare function GetProcAddress lib "KERNEL32.DLL" alias "GetProcAddress" (byval hModule as dword, lpProcName as asciiz) as long
declare function LoadLibrary lib "KERNEL32.DLL" alias "LoadLibraryA" (lpLibFileName as asciiz) as long
'===========================================================================
declare function EntryPoint(byval hInstance as dword, byval Reason as dword, byval Reserved as dword) as long

function GetProcAddressDirectly (byval lpImageDosHeader as IMAGE_DOS_HEADER ptr, FuncName as asciiz) as dword
    local lpImageNtHeaders as IMAGE_NT_HEADERS ptr
    local lpImageExportDirectory as IMAGE_EXPORT_DIRECTORY ptr
    local lpNameOrdinals as word ptr
    local lpName, lpFunctions as dword ptr
    local lpFuncName, lpExpFuncName as asciiz ptr
    local i, j as dword

    if (@lpImageDosHeader.e_magic <> IMAGE_DOS_SIGNATURE) then
        function = 1: exit function ' invalid DOS signature
    end if
    lpImageNtHeaders = lpImageDosHeader + @lpImageDosHeader.e_lfanew
    if (@lpImageNtHeaders.Signature <> IMAGE_NT_SIGNATURE) then
        function = 1: exit function ' invalid NT signature
    end if
    if (@lpImageNtHeaders.FileHeader.SizeOfOptionalHeader <> sizeof(@lpImageNtHeaders.OptionalHeader) or _
        @lpImageNtHeaders.OptionalHeader.Magic <> IMAGE_NT_OPTIONAL_HDR32_MAGIC) then
        exit function
    end if

    lpImageExportDirectory = @lpImageNtHeaders.OptionalHeader.DataDirectory(IMAGE_DIRECTORY_ENTRY_EXPORT).VirtualAddress
    if (lpImageExportDirectory = 0) then
        exit function
    end if
    lpImageExportDirectory = lpImageExportDirectory + lpImageDosHeader

    lpNameOrdinals = @lpImageExportDirectory.AddressOfNameOrdinals + lpImageDosHeader
    lpName         = @lpImageExportDirectory.AddressOfNames        + lpImageDosHeader
    lpFunctions    = @lpImageExportDirectory.AddressOfFunctions    + lpImageDosHeader

    lpFuncName = varptr(FuncName)

    if (HI(WORD, lpFuncName)) then ' Name
        for i = 0 to @lpImageExportDirectory.NumberOfFunctions - 1
            if (@lpFunctions[i]) then
                for j = 0 to @lpImageExportDirectory.NumberOfNames - 1
                   if (@lpNameOrdinals[j] = i) then
                       lpExpFuncName = @lpName[j] + lpImageDosHeader
                       if (@lpExpFuncName = FuncName) then
                           function = @lpFunctions[i] + lpImageDosHeader
                           exit function
                       end if
                   end if
                next
            end if
        next
    else
        for i = 0 to @lpImageExportDirectory.NumberOfFunctions - 1
            if (lpFuncName = @lpImageExportDirectory.nBase + i) then
                if (@lpFunctions[i]) then
                    function = @lpFunctions[i] + lpImageDosHeader
                end if
                exit function
            end if
        next
    end if
end function

function LoadDllfromMemory (byval lpRawDll as dword, byval RawDllSize as dword, lpImageDll as dword) as long
    local nError as long
    local sSysInfo as SYSTEM_INFO
    local lpImageDosHeader        as IMAGE_DOS_HEADER ptr
    local lpImageNtHeaders        as IMAGE_NT_HEADERS ptr
    local lpImageSectionHeader    as IMAGE_SECTION_HEADER ptr
    local lpImageImportDescriptor as IMAGE_IMPORT_DESCRIPTOR ptr
    local lpImageImportByName     as IMAGE_IMPORT_BY_NAME ptr
    local lpImageBaseRelocTable   as IMAGE_BASE_RELOCATION ptr
    local lpDllName               as asciiz ptr
    local szDllName               as string
    local lpTypeOffset            as word ptr
    local TpOffset                as word
    local lpFuncNameRef, lpFuncAddr, lpLink as dword ptr
    local ImagePages, hDll, fOldProtect, i, j, k, Pg, Pg1, Pg2, Addr1, Addr2 as dword
    local Protection() as byte

    lpImageDosHeader = lpRawDll
    if (RawDllSize < sizeof(IMAGE_DOS_HEADER)) then
        nError = 1: goto BailOut
    end if
    if (@lpImageDosHeader.e_magic <> IMAGE_DOS_SIGNATURE) then
        nError = 1: goto BailOut ' invalid DOS signature
    end if
    if (RawDllSize < @lpImageDosHeader.e_lfanew + sizeof(IMAGE_NT_HEADERS)) then
        nError = 1: goto BailOut
    end if
    lpImageNtHeaders = lpImageDosHeader + @lpImageDosHeader.e_lfanew
    if (@lpImageNtHeaders.Signature <> IMAGE_NT_SIGNATURE) then
        nError = 1: goto BailOut ' invalid NT signature
    end if
    if (@lpImageNtHeaders.FileHeader.SizeOfOptionalHeader <> sizeof(@lpImageNtHeaders.OptionalHeader) or _
        @lpImageNtHeaders.OptionalHeader.Magic <> IMAGE_NT_OPTIONAL_HDR32_MAGIC) then
        nError = 1: goto BailOut
    end if
    if (@lpImageNtHeaders.FileHeader.NumberOfSections < 1) then
        nError = 1: goto BailOut
    end if

    for i = 0 to IMAGE_NUMBEROF_DIRECTORY_ENTRIES - 1
        if (@lpImageNtHeaders.OptionalHeader.DataDirectory(i).VirtualAddress <> 0) then
            select case as long i
            case IMAGE_DIRECTORY_ENTRY_EXPORT     ' Export Directory
            case IMAGE_DIRECTORY_ENTRY_IMPORT     ' Import Directory
            case IMAGE_DIRECTORY_ENTRY_RESOURCE   ' Resource Directory
            case IMAGE_DIRECTORY_ENTRY_BASERELOC  ' Base Relocation Table
            case IMAGE_DIRECTORY_ENTRY_IAT        ' Import Address Table
            case else ' Strange for PB
                nError = 2: goto BailOut
            end select
        end if
    next

    lpImageSectionHeader = lpImageNtHeaders + sizeof(IMAGE_NT_HEADERS)
    k = lpImageSectionHeader - lpImageDosHeader + sizeof(IMAGE_SECTION_HEADER) * @lpImageNtHeaders.FileHeader.NumberOfSections
    j = k
    for i = 0 to @lpImageNtHeaders.FileHeader.NumberOfSections - 1
        j = max(j, @lpImageSectionHeader[i].VirtualAddress + @lpImageSectionHeader[i].SizeOfRawData)
    next

    GetSystemInfo(sSysInfo)
    ImagePages = j \ sSysInfo.dwPageSize
    if (j Mod sSysInfo.dwPageSize) then incr ImagePages
    lpImageDll = VirtualAlloc(byval 0, cdwd(ImagePages * sSysInfo.dwPageSize), MEM_COMMIT, PAGE_EXECUTE_READWRITE)
    if (lpImageDll = 0) then
        nError = 5: goto BailOut
    end if

    MoveMemory(byval lpImageDll, byval lpRawDll, k)
    for i = 0 to @lpImageNtHeaders.FileHeader.NumberOfSections - 1
        MoveMemory(byval cdwd(lpImageDll + @lpImageSectionHeader[i].VirtualAddress), _
                   byval cdwd(lpRawDll + @lpImageSectionHeader[i].PointerToRawData), @lpImageSectionHeader[i].SizeOfRawData)
    next

    '// Switch to new image
    lpImageDosHeader = lpImageDll
    lpImageNtHeaders = lpImageDosHeader + @lpImageDosHeader.e_lfanew
    lpImageSectionHeader = lpImageNtHeaders + sizeof(IMAGE_NT_HEADERS)

    '// Start Original code BY Lothar
    lpImageImportDescriptor = @lpImageNtHeaders.OptionalHeader.DataDirectory(IMAGE_DIRECTORY_ENTRY_IMPORT).VirtualAddress
    if (lpImageImportDescriptor <> 0) then
        lpImageImportDescriptor = lpImageImportDescriptor + lpImageDosHeader

        while @lpImageImportDescriptor.OriginalFirstThunk <> 0 or @lpImageImportDescriptor.FirstThunk <> 0 ' Dlls
            lpDllName = @lpImageImportDescriptor.pName + lpImageDosHeader
            szDllName = @lpDllName
            hDll = GetModuleHandle(byval strptr(szDllName))

            if (hDll = 0) then hDll = LoadLibrary(byval strptr(szDllName))
            if (hDll = 0) then
                nError = 2: goto BailOut '// Can't find
            end if

            lpFuncNameRef = @lpImageImportDescriptor.OriginalFirstThunk + lpImageDosHeader

            lpFuncAddr = @lpImageImportDescriptor.FirstThunk + lpImageDosHeader
            if lpFuncNameRef = lpImageDosheader then lpFuncNameRef = lpFuncAddr

            while @lpFuncNameRef <> 0
                lpImageImportByName = @lpFuncNameRef + lpImageDosHeader

                if (@lpFuncNameRef and IMAGE_ORDINAL_FLAG) then
                    @lpFuncAddr = GetProcAddress(hDll, byval @lpFuncNameRef and &HFFFF???)
                else
                    @lpFuncAddr = GetProcAddress(hDll, @lpImageImportByName.ImpName)
                end if

                if (@lpFuncAddr = 0) then
                    nError = 2: goto BailOut
                end if
                incr lpFuncAddr
                incr lpFuncNameRef
            wend
            incr lpImageImportDescriptor
        loop

    end if
    '// End Original code BY Lothar

    lpImageBaseRelocTable = @lpImageNtHeaders.OptionalHeader.DataDirectory(IMAGE_DIRECTORY_ENTRY_BASERELOC).VirtualAddress
    if (lpImageBaseRelocTable <> 0) then
        lpImageBaseRelocTable = lpImageBaseRelocTable + lpImageDosHeader
        while @lpImageBaseRelocTable.VirtualAddress <> 0
            lpTypeOffset = lpImageBaseRelocTable + sizeof(IMAGE_BASE_RELOCATION)
            while lpTypeOffset < lpImageBaseRelocTable + @lpImageBaseRelocTable.SizeOfBlock
                TpOffset = @lpTypeOffset and &HF000??
                if (TpOffset = &H3000) then
                    lpLink = lpImageDosHeader + @lpImageBaseRelocTable.VirtualAddress + (@lpTypeOffset and &HFFF??)
                    @lpLink = @lpLink - @lpImageNtHeaders.OptionalHeader.ImageBase + lpImageDosHeader
                elseif TpOffSet = 0 then
                else
                    nError = 3: goto BailOut ' Uknown type
                end if
                incr lpTypeOffset
            wend
            lpImageBaseRelocTable = lpImageBaseRelocTable + @lpImageBaseRelocTable.SizeOfBlock
        wend
    end if

    redim Protection(ImagePages - 1)

    for i = 0 to @lpImageNtHeaders.FileHeader.NumberOfSections
        if (i = @lpImageNtHeaders.FileHeader.NumberOfSections) then
            Addr1 = 0: Addr2 = k: j = &H60000000??? '// PAGE_EXECUTE_READ
        else
            Addr1 = @lpImageSectionHeader[i].VirtualAddress
            Addr2 = @lpImageSectionHeader[i].SizeOfRawData
            j = @lpImageSectionHeader[i].Characteristics
        end if
        Addr2 = Addr1 + Addr2 - 1
        Pg1 = Addr1 \ sSysInfo.dwPageSize
        Pg2 = Addr2 \ sSysInfo.dwPageSize
        for Pg = Pg1 to Pg2
            if (j and &H20000000???) then Protection(Pg) = Protection(Pg) or 1 ' Execute
            if (j and &H40000000???) then Protection(Pg) = Protection(Pg) or 2 ' Read
            if (j and &H80000000???) then Protection(Pg) = Protection(Pg) or 4 ' Write
        next
    next
    Addr1 = lpImageDosHeader
    for Pg = 0 to ImagePages - 1
        select case as long Protection(Pg)
        case 2: fOldProtect = PAGE_READONLY
        case 3: fOldProtect = PAGE_EXECUTE_READ
        case 6: fOldProtect = PAGE_READWRITE
        case else: fOldProtect = PAGE_EXECUTE_READWRITE ' Ignore strange combinations
        end select
        if (fOldProtect <> PAGE_EXECUTE_READWRITE) then
           if (VirtualProtect (byval Addr1, sSysInfo.dwPageSize, fOldProtect, fOldProtect) = 0) then
               nError = 4: goto BailOut
           end if
        end if
        Addr1 = Addr1 + sSysInfo.dwPageSize
    next

    i = @lpImageNtHeaders.OptionalHeader.AddressOfEntryPoint + lpImageDosHeader
    CALL DWORD i using EntryPoint (lpImageDosHeader, DLL_PROCESS_ATTACH, 0)

BailOut:
    function = nError
end function

function Unload_DLL (byval lpImageDosHeader as IMAGE_DOS_HEADER ptr) as dword
    local lpImageNtHeaders as IMAGE_NT_HEADERS ptr
    local i as dword

    lpImageNtHeaders = lpImageDosHeader + @lpImageDosHeader.e_lfanew
    i = @lpImageNtHeaders.OptionalHeader.AddressOfEntryPoint + lpImageDosHeader
    CALL DWORD i using EntryPoint (lpImageDosHeader, DLL_PROCESS_DETACH, 0)
    function = VirtualFree (byval lpImageDosHeader, 0, MEM_RELEASE)
end function

function Load_DLL(lpName as ASCIIZ) as dword
    local nError as long
    local hLib, hResource, buffersize, pResourceData, hInstance as DWORD
    hInstance = GetModuleHandle("")
    hResource = FindResource(hInstance, lpName, byval RT_RCDATA)
    if (hResource) then
        buffersize = SizeofResource(hInstance, hResource)
        if (buffersize > 0) then
            pResourceData = LockResource(LoadResource(hInstance, hResource))
            if (pResourceData) then
                nError = LoadDllfromMemory(byval pResourceData, buffersize, hLib)
                if (nError) then hLib = 0
            end if
        end if
    end if
    function = hLib
end function

function Load_DLL((lpName as ASCIIZ)) as dword
is used to load the DLL from resource.
« Last Edit: January 26, 2022, 02:38:25 pm by Patrice Terrier »
Patrice
(Always working with the latest Windows version available...)