Here is a piece of sample code to retrieve data from a compiled in resource. This sample was used to store and execute a SQL script from inside a dll or exe.
To create .res files i used XNReshourceEditor.exe (free download). Add the generated resource to library includes.
The trick is to: Do not mess up the HANDLEs!
Usage:
GetResource('DATA.DLL', 'SQL', 'WHO_IS_ACTIVE_V11_32', SQL)
Dummy{PROP:SQL} = SQL
IF ERRORCODE() THEN Message(Dummy{PROP:SQL}, 'Error in GetResource script') END
Inside Global map:
MODULE('Win32API')
GetModuleHandle(*CSTRING pModuleName), HMODULE, PASCAL, RAW, NAME('GetModuleHandleA') ! return handle/instance of module
GetModuleHandleRaw(UNSIGNED pModuleName), HMODULE, PASCAL, RAW, NAME('GetModuleHandleA') ! return handle/instance of module
FindResource(HINSTANCE,*CSTRING,*CSTRING),HANDLE,PASCAL,RAW,NAME('FindResourceA')
SizeofResource(HINSTANCE, HANDLE),DWORD,PASCAL
LoadResource(HINSTANCE, HANDLE),HGLOBAL,PASCAL
LockResource(HGLOBAL),LONG,PASCAL
FreeResource(HGLOBAL),LONG,PASCAL
MemCpy(LONG dest, LONG src, LONG count), LONG, RAW, PROC, NAME('_memcpy')
END
The code:
GetResource PROCEDURE (<STRING pModule>,STRING pType,STRING pID,*CSTRING pData) ! Declare Procedure
aResourceID CSTRING(65)
aResourceType CSTRING(65)
aModule CSTRING(65)
aModuleHandle HMODULE
aResourceHandle HANDLE
aResourceSize DWORD
aResourceMemory HGLOBAL
aPointer LONG
CODE
GlobalErrors.SetProcedureName('GetResource')
aModule = pModule
aModuleHandle = GetModuleHandle(aModule)
IF NOT aModuleHandle THEN ! Get Handle of current module by API null if not found by name
aModuleHandle = GetModuleHandleRaw(0)
aModule = 0 ! set value for debugoutput
END
IF aModuleHandle THEN
aResourceType = pType
aResourceID = pID
aResourceHandle = FindResource(aModuleHandle, aResourceID, aResourceType)
IF aResourceHandle THEN
aResourceSize = SizeOfResource(aModuleHandle, aResourceHandle)
DebugOutput('Resource Size=' & aResourceSize & ' for ' & aModule & '\' & aResourceType & '\' & aResourceID)
aResourceMemory = LoadResource(aModuleHandle, aResourceHandle)
IF aResourceMemory THEN
aPointer = LockResource(aResourceMemory)
IF aPointer THEN
MemCpy(ADDRESS(pData), aPointer, aResourceSize)
pData[aResourceSize + 1] = '<0>' ! Resources are not required to end with a null character and could have null characters inside them.
DebugOutput('Loaded Resource ' & aModule & '\' & aResourceType & '\' & aResourceID & ' data=' & SUB(pData, 1, CHOOSE(aResourceSize < 1024, aResourceSize, 1024)))
ELSE
MESSAGE('Could not retreive resource memory pointer for ' & aModule & '\' & aResourceType & '\' & aResourceID)
END
! FreeResource(aResourceMemory) ! [This function is obsolete and is only supported for backward compatibility with 16-bit Windows. For 32-bit Windows applications, it is not necessary to free the resources loaded using LoadResource.]
ELSE
MESSAGE('Could not retreive resource memory handle for ' & aModule & '\' & aResourceType & '\' & aResourceID)
END ! IF aResourceMemory
ELSE
MESSAGE('Could not retreive resource handle for ' & aModule & '\' & aResourceType & '\' & aResourceID)
END ! IF aResourceHandle
ELSE
MESSAGE('Could not retreive module handle for ' & aModule)
END ! IF aModuleHandle
GlobalErrors.SetProcedureName()
- Missing datatypes can be found in Windows.inc