Odd sharing access violation (OS Error 32) with Freepascal implementation of libEWF

343 views Asked by At

I am hoping to implement the workings of a C library called libEWF (by Joachim Metz) into my Freepascal program. A chap called Erwan has already converted an earlier version of the library to Delphi early last year sometime, which I have an in turn tweaked a little for use with Freepascal.

My problem relates to OS Error code 32 'access sharing violation' which is returned by the following code and suggests there is a problem with accessing the output file (which is created as a zero byte file but nothing is ever written to it).

uses
LibEWFUnit, Windows, ....  
// Image\backup disk using EWF image format, return bytes imaged
function WindowsImageDiskEWF(hDiskHandle : THandle; DiskSize : Int64) : Int64;
var
  Buffer  : array [0..32767] of Byte; 
  fLibEWF : TLibEWF;

begin

  // Initilise the libEWF instance
  fLibEWF:=TLibEWF.create;
  fLibEWF.libewf_SetCompressionValues(1,0);
  fLibEWF.libewf_SetHeaderValue('acquiry_software_version','YAFFI');

  // Create and open the output file, .e.g MyImage.E01 with write access      
  if fLibEWF.libewf_open(frmYaffi.ledtImageName.Text,LIBEWF_OPEN_WRITE)=0 then
  begin
  try      
  // Now to seek to start of device
   FileSeek(hDiskHandle, 0, 0);
     repeat
       // Read source device handle in buffered segments. 
       BytesRead     := FileRead(hDiskHandle, Buffer, SizeOf(Buffer));
       if BytesRead = -1 then
         begin
           RaiseLastOSError;
           exit;
         end;
       inc(TotalBytesRead, BytesRead);

       // Now write buffer to libEWF instance, but -1 keeps being returned
       BytesWritten  := fLibEWF.libewf_write_random(@Buffer, SizeOf(Buffer), TotalBytesRead);         
       if BytesWritten = -1 then
         begin
           RaiseLastOSError;  //THIS KEEPS BEING RAISED : OS ERROR 32
           exit;
         end;          
       inc(TotalBytesWritten, BytesWritten);
   .....
   finally
     fLibEWF.libewf_close;
   ..... 
  end;
end;

and on it is supposed to go until TotalBytesRead equals the size of the input device.

However, as the notes show, for some reason, -1 is always being returned by

BytesWritten  := fLibEWF.libewf_write_random(@Buffer, SizeOf(Buffer), BytesRead);

and RaiseLastOSError keeps generating OS error code 32 - access sharing violation. Using UnlockIT to check if anything else has a hold on the image file file, it shows only my prgram does. Same goes for the DLL file that comes with the converted library that Erwan supplies.

I have tried contacting Erwan to see if he can help (as he manages to create E01 backup files with his utility CloneDisk which uses this same library but with Delphi) but an answer has not arrived yet and may never do. So I am hoping someone can offer me guidance on how to resolve this? Joachim Metz has been good enough to reply to me but he clearly has many projects on but despite that he was good enough to tell me that the sharing rights are assigned by this other library, line 505 of libcfile_file.c. But as my unit is from an earlier version of libEWF that was then converted to Delphi and then to Freepascal, I don't think I can use or rely on that.

The converted Delphi unit that I have tweaked for use with Freepascal is visible HERE. It is line 301 of that file that makes result = -1 which is how BytesWritten subsequently becomes equal to -1 and therefore fails. If anyone can see what changes I need to make, I'd be obliged.

And before anyone says "just convert the C library to a pascal unit", can I suggest you try to do that before suggesting it! If it was that easy, I'd download the latest and most recent master from https://github.com/libyal/libewf and create a new, fresh DLL and unit with all the modernisations. But I've spent three days battling with that concept and been met with nothing but failure.So Erwans Delphi unit is the best hope I have. Thanks

1

There are 1 answers

4
J... On

RaiseLastOSError is probably not even relevant here. In Erwan's Delphi implementation the call to libewf_write_random looks like :

function TLibEWF.libewf_write_random(buffer : pointer; 
                                     size : longword; 
                                     offset : int64) : integer;
var
  err:pointer;
begin
  err:=nil;
  Result:=-1;
  if fLibHandle<>0 then begin
    if LIBEWF_VERSION='V1' then 
      Result:=fLibEWFWriteRand(fCurEWFHandle, buffer, size, offset);
    if LIBEWF_VERSION='V2' then 
      Result:=flibewfhandlewriterandom(fCurEWFHandle, buffer, size, offset,@err);
  end;
end;

Since version V2 is most likely current and you are most likely using version 2, and since version 2 provides error information, this Delphi implementation is hiding the error information returned by LibEWF. There is extensive error checking and handling in the C library. The method signature for this write method resolves to :

 ssize_t libewf_handle_write_buffer(libewf_handle_t *handle,
                                    const void *buffer,
                                    size_t buffer_size,
                                    libcerror_error_t **error )

where the error argument is a pointer to a structure (standard libcerror structure) that contains the detailed error information that would assist your debugging. For example, one of dozens of such calls in libewf_handle_write_buffer :

if( internal_handle->current_offset < 0 )
{
    libcerror_error_set(
     error,               
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
     "%s: invalid handle - invalid IO handle - current offset value out of bounds.",
     function );

    return( -1 );
}

In all cases where libewf_write_random returns -1 the underlying library call also returns error information. This is the error information you need to be checking. There seems no way to do this with the current Delphi implementation you are using. I would strongly suggest that you write your own wrapper for the LibEWF DLL, or modify the one you have, such that it retrieves this error information. This will tell you where the real problem lies. Surely the error is not an I/O 32 error.