unit Resu; not used
{ Using EXE/DLL/RES files for storing/accessing data }
interface
uses
  Windows;

{ Opens file handle access to given resource and returns 0 if OK
  and fills ASize with size of the resource data in resource file
  (original data padded with 0 to modulo X size).
  Use ResFileDataClose method when finished reading using
  ResFileDataReadLn methods.

  If AModuleHandle > 0 then the AModuleName was loaded during
  the call and should be unloaded by FreeLibrary call when not used
  anymore.

  Beware!!!: using FRead,FReadLn methods reading continues even after
  size of resource already read, so control how many bytes were read.

  Following ResFileDataReadLn can be used if data is ASCII text, instead
  of FReadLn. It controls the ASize (decrements it) and #0 chars
  (used by compiler for padding of resource to modulo 256 size).
  Returns <> 0 if no more data. }

function ResFileDataOpen(const AModuleName: string; const AResName: string;
  var ASize: longint; var AResHandle: PResHandle; var AModuleHandle: THandle): integer;

  { Reads ASCII data from resource that was opened using the above method.
    ASizeToRead = ASize (got from ResFileDataOpen), gets decremented by
    every call by number of chars filled to ALine, eventually by number
    of CR/LF chars. Returns 0 if read OK, <> 0 if no more data. }
function ResFileDataReadLn(AResHandle: PResHandle; var ASizeToRead: longint;
  var ALine: string): integer;

function ResFileDataClose(var AResHandle: PResHandle): integer;

{ Tries to load raw data with name AResName from AModuleName.
  If extension of AModuleName is not given then files with extensions
  EXE,DLL,RES are tried in this order.
  Resource files created using BRC compiler (brc -r xxxx.rc)
  from .RC files, that can have following formats:
  1.
  AResName RCDATA
  BEGIN
    10 20 0xAF 077 ...
    'AFBC10CD'
    "text in ascii"
  END

  2.
  AResName RCDATA
  NameOfFileWithData

  Beware, data in resource file are padded with 0 to have n*256
  size.

  AData should be freed if not needed anymore.
}
function ResFileDataLoad(const AModuleName: string; const AResName: string;
  var AData: pointer; var ADataSize: longint): integer;{$IFDEF PMODE}export;{$ENDIF}

implementation

const
  GLastResult: TResourceResult = rrOK;
  ExtCount = 2;
  Exts: array[0..ExtCount-1] of ExtStr = (ExeExt, DLLExt);

procedure ClearResult;
begin
  GLastResult := rrOK;
end;

procedure SetResult(rr:TResourceResult; const msg:string);
begin
  GLastResult := rr;
  case rr of
    rrOK, frEOF:;
  else
    SysLogLog(leError, 'RESU: ' + IntToStr(rr) + ' ' + msg);
  end;
end;

{$IFDEF PMODE}
function ResFileDataOpen(const AModuleName: string; const AResName: string;
  var ASize: longint; var AResHandle: PResHandle; var AModuleHandle: THandle): integer;
  { Opens file handle access to given resource and returns rrOK if OK
    and fills ASize with size of the resource data in resource file
    (original data padded with 0 to modulo 256 size).
    Use crtu. FClose method when finished reading using FRead, FReadLn
    methods. If AModuleHandle > 0 then the AModuleName was loaded during
    the call and should be unloaded (dllutl.DLLFree, eventually FreeLibrary
    if not in GHS system)  when not used anymore }
var
  d, n, e: string;
  fn: string;
  cnt: integer;
  ResInfo: THandle;
  mn, rn: array[0..255] of char;
  modHandle: THandle;
  AHandle: TFileHandle;
  size: longint;
label ex;
begin
  ClearResult;
  FSplit(AModuleName, d, n, e);
  cnt := 0;
  StrPCopy(rn, AResName);
  AModuleHandle := 0;
  ResInfo := 0;
  ASize := 0;
  AResHandle := nil;
  modHandle := 0;
  repeat
    if e = '' then
      fn := d + n + Exts[cnt]
    else
      fn := d + n + e;
    if fn = '' then begin
      modHandle := SysGetPropInt(spCurHInstance);
    end else begin
      StrPCopy(mn, fn);
      modHandle := GetModuleHandle(mn);
    end;

    if (modHandle < MinValidDLLHandle) then begin
      if (fn <> '') and DLLLoad(fn, false, modHandle) then begin
        AModuleHandle := modHandle;
      end else begin
        if (e <> '') or (cnt = ExtCount - 1) then begin
          SetResult(rrModuleLoadFailed, AModuleName);
          goto ex;
        end;
      end;
    end;

    if modHandle >= MinValidDLLHandle then begin
      ResInfo := FindResource(modHandle, rn, rt_rcdata);
      if ResInfo > 0 then begin
        size := SizeOfResource(modHandle, ResInfo);
        if size = 0 then begin
          SetResult(rrZeroSize, '');
          goto ex;
        end;
        AHandle := AccessResource(modHandle, ResInfo);
        if AHandle > 0 then begin
          ASize := size;
          AResHandle := New(PTextStream, InitFromHandle(AHandle, 1024));
          goto ex;
        end else begin
          SetResult(rrAccessResourceFailed, fn + '.' + AResName);
          goto ex;
        end;
      end else begin
        { resource not found }
        if AModuleHandle <> 0 then begin
          DLLFree(AModuleHandle);
        end;
        if (e <> '') or (cnt = ExtCount - 1) then begin
          SetResult(rrFindResouceFailed, fn + '.' + AResName);
          goto ex;
        end;
      end;
    end else begin

    end;
    inc(cnt);
    if (e <> '') or (cnt >= ExtCount) then begin
      SetResult(rrFailed,'');
      goto ex;
    end;
  until false;
ex:
  ResFileDataOpen := GLastResult;
end;

function ResFileDataReadLn(AResHandle: PResHandle; var ASizeToRead: longint;
  var ALine: string): integer;
  { Reads ASCII data from resource that was opened using the above method.
    ASizeToRead = ASize (got from ResFileDataOpen), gets decremented by
    every call by number of chars filled to ALine, eventually by number
    of CR/LF chars. Returns 0 if read OK, <> 0 if no more data. }
var
  toread, read: word;
  r: TFileResult;
  p: integer;
  st: PTextStream absolute AResHandle;
label ex;
begin
  ClearResult;
  if ASizeToRead <= 0 then begin
    SetResult(frEOF,'');
    goto ex;
  end;
  toread := 255;
  if toread > ASizeToRead then
    toread := ASizeToRead;
  read := 0;
  if st^.EOF then begin
    {r := FReadLn(AHandle, ALine, toread, read);
    if r <> frOK then begin}
    SetResult(frEOF,'');{filetype}
    goto ex;
  end else begin
    st^.ReadLn(ALine);
    read := length(ALine) + 2;
  end;
  Dec(ASizeToRead, read);
  p := pos(#0, ALine);
  if p <> 0 then begin
    ALine := copy(ALine, 1, p - 1);
    if ALine = '' then begin
      SetResult(frEOF,'');
      goto ex;
    end;
  end;
ex:
  ResFileDataReadLn := GLastResult;
end;

function ResFileDataClose(var AResHandle: PResHandle): integer;
var st: PTextStream absolute AResHandle;
begin
  FreeObject(@st);
  ResFileDataClose := 0;
end;

function ResFileDataLoad(const AModuleName: string; const AResName: string;
  var AData: pointer; var ADataSize: longint): TResourceResult;
var
  d, n, e: string;
  fn: string;
  cnt: integer;
  ModHandle: THandle;
  ResInfo: THandle;
  ResData: THandle;
  mn, rn: array[0..255] of char;
    { module name }
  loaded: boolean;
    { was the module loaded during this call? }
  data: pointer;
  size: longint;
label ex;
begin
  ClearResult;
  FSplit(AModuleName, d, n, e);
  cnt := 0;
  loaded := false;
  StrPCopy(rn, AResName);
  ModHandle := 0;
  ResInfo := 0;
  ResData := 0;
  AData := nil;
  ADataSize := 0;
  repeat
    if e = '' then
      fn := d + n + Exts[cnt]
    else
      fn := d + n + e;
    StrPCopy(mn, fn);
    ModHandle := GetModuleHandle(mn);

    if ModHandle < MinValidDLLHandle then begin
      if DLLLoad(fn, false, ModHandle) then begin
        loaded := true;
      end else begin
        if (e <> '') or (cnt = ExtCount - 1) then begin
          SetResult(rrModuleLoadFailed, AModuleName);
          goto ex;
        end;
      end;
    end;

    if ModHandle >= MinValidDLLHandle then begin
      ResInfo := FindResource(ModHandle, rn, rt_rcdata);
      if ResInfo > 0 then begin
        size := SizeOfResource(ModHandle, ResInfo);
        if size = 0 then begin
          SetResult(rrZeroSize, '');
          goto ex;
        end;
        if size > MaxBufSize then begin
          SetResult(rrSizeToBig, IntToStr(size));
          goto ex;
        end;
        if not MemGet(AData, size {$IFDEF DEBMEM},piResFileDataLoad{$ENDIF}) then begin
          SetResult(rrOOM, 'MemGet');
          goto ex;
        end;
        ResData := LoadResource(ModHandle, ResInfo);
        if ResData > 0 then begin
          data := LockResource(ResData);
          move(data^, AData^, size);
          ADataSize := size;
          UnlockResource(ResData);
          FreeResource(ResData);
          goto ex;
        end else begin
          SetResult(rrLoadResourceFailed, fn + '.' + AResName);
          goto ex;
        end;
      end else begin
        { resource not found }
        if loaded then begin
          loaded := false;
          DLLFree(ModHandle);
        end;
        if (e <> '') or (cnt = ExtCount - 1) then begin
          SetResult(rrFindResouceFailed, fn + '.' + AResName);
          goto ex;
        end;
      end;
    end else begin

    end;
    inc(cnt);
    if (e <> '') or (cnt >= ExtCount) then begin
      SetResult(rrFailed,'');
      goto ex;
    end;
  until false;
ex:
  if loaded then
    DLLFree(ModHandle);
  if (ADataSize = 0) and (AData <> nil) then
    MemFree(AData, size{$IFDEF DEBMEM},piResFileDataLoad{$ENDIF});
  ResFileDataLoad := GLastResult;
end;

end.

