Link to home
Start Free TrialLog in
Avatar of DickStorey
DickStorey

asked on

ReadFile error ERROR_NOACCESS

I have translated the modified async filter from the DirectShow SDK to Delphi.  I have a problem with ReadFile on a local media file opened with GENERIC_READ, FILE_SHARE_READ and FILE_FLAG_OVERLAPPED.

It returns ERROR_NOACCESS.  The parameters going into the call are the same in C++ and in Delphi but Delphi returns
ERROR_NOACCESS whereas C++ returns ERROR_IO_PENDING

Any Ideas what the problem might be?
// Create the file
function TFileStream.Initialize(Filename: string): HResult;
begin
  if FFileHandle <> INVALID_HANDLE_VALUE then
  begin
    Result := E_FAIL;
    exit;
  end;
 
  FFileHandle := CreateFile(PChar(filename), GENERIC_READ, FILE_SHARE_READ,
    nil, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
 
  if FFileHandle = INVALID_HANDLE_VALUE then
    Result := HResultFromWin32(GetLastError)
  else
    Result := S_OK;
end;
 
// Attempt to read it
function TFileStream.StartRead(Buffer: PByte; BytesToRead: Cardinal;
  Align: boolean; Overlapped: POverlapped; var Pending: boolean;
  var BytesRead: cardinal): HResult;
var
  res: BOOL;
  err: DWORD;
begin
  Pending := false;
 
  Lock;
  try
    // all these parameters are valid
    res := ReadFile(FFileHandle, Buffer, BytesToRead, BytesRead, Overlapped);
 
    if not res  then
    begin
      err := GetLastError;
      if (err = ERROR_IO_PENDING) then
      begin
        Pending := true;
        Result := S_OK;
      end
      else if err = ERROR_NOACCESS then // why does this happen?
      begin
        Beep;
        Result := HResultFromWin32(err);
      end
      else
        Result := HResultFromWin32(err);
    end
    else
      Result := S_OK;
  finally
    UnLock;
  end;
end;

Open in new window

Avatar of Lukasz Zielinski
Lukasz Zielinski
Flag of Poland image

ERROR_NOACCESS means: "Invalid access to memory location" I guess something is wrong with your buffer

ziolko.
make sure Buffer is allocated and try changing function declaration to:
function TFileStream.StartRead(var Buffer: PByte;...

ziolko.
I'm confused... Doesn't delphi already have a TFileStream class? Why are you creating one?

if you are, in fact using the delphi one, then please paste your call that creaets teh TFileStream

e.g.
var
  fs: TFileStream;
begin
  fs := TFileStream.Create('file.txt', fmOpenRead OR fmShareDenyNone);
  try
   ...
  finally
    fs.free;
  end;
end;

fwiw, if you are using this, then I suspect you are not opening it as readonly (you said it was on a media)
@TheRealLoki: looks like he wants asynchrnious read operation (he uses overlapped structure) but indeed class name is a little bit confusing

ziolko.
Avatar of DickStorey
DickStorey

ASKER

Hi ziolko and TheRealLoki

Sorry, I'm new to using this site and I realise I did not give a detailed enough problem description.  I cannot find a means to modify my question so I am adding a comment in the hope you might notice it and tell me how to do so.

I'm aware Delph has a TFileStream class, which I am not using.  My code is a direct translation of an improved version of the DirectShow SDK's async filter.  The name FileStream may be confusing to a Delphi developer but it describes the function of the class in my code.

The DirectShow filter does indeed use asynchronous reading since it may be accessing media files of several gigabytes on remote storage and starting from any point within the file. I have the C++ version and the Delphi version available to trace.  The Buffer comes from an Elecard mpeg demultiplexer and is known to be good.  The parameters going into the function, even the address of the buffer, are identical in the C++ version and the Delphi version (which is surprising in itself).  The Overlapped structure is initialised in another function and given an event as per the C++ example.  The content of the Overlapped structure is alsp the same.

I have tried using a locally generated buffer within the function and the behaviour depends upon the filter read size.  For small sizes the function succeeds but there is no data in the buffer, for large sizes, the function fails as it should but with an error of 998(ERROR_NOACCESS)  instead of 997 (ERROR_IO_PENDING).  Interestingly, the parameters in the Overlapped structure after the ReadFile are the same in the C++ and Delphi versions indicating that the call has behaved similarly in both cases, its just that the outcome is different.  Its almost as if the definition of ReadFile in Windows.pas:

function ReadFile(hFile: THandle; var Buffer; nNumberOfBytesToRead: DWORD;
  var lpNumberOfBytesRead: DWORD; lpOverlapped: POverlapped): BOOL; stdcall;
{$EXTERNALSYM ReadFile}

is not working as expected.  I'm using RADStudio 2007 for my Delphi coding.

ASKER CERTIFIED SOLUTION
Avatar of Lukasz Zielinski
Lukasz Zielinski
Flag of Poland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial