Search code examples
filedelphipascal

TFileStream.Create - Open read write but allow others to readonly


I am facing a situation where I need to open a file in readonly mode when the same exe might have already opened the same file (network share) in read/write mode. I must allow other users to at least read that file.

The EXE will be launched simultaneously by many different users on their machines pointing to the same shared file.

I am facing "Cannot open file '<file>'. The process cannot access the file because it is being used by another process" Error.

Is there any way that this could be solved?

Code to open in read/write mode

TFileStream.Create(<file>, fmOpenReadWrite or fmShareDenyNone);

Code to open in read only mode

TFileStream.Create(<file>, fmOpenRead);

Solution

  • As per this table (do not look up the current version with messed up layout semantics) the second call must at least have the same sharing:

    First call to CreateFile Valid second calls to CreateFile
    GENERIC_READ | GENERIC_WRITE with FILE_SHARE_READ | FILE_SHARE_WRITE GENERIC_READ with FILE_SHARE_READ | FILE_SHARE_WRITE
    GENERIC_WRITE with FILE_SHARE_READ | FILE_SHARE_WRITE
    GENERIC_READ | GENERIC_WRITE with FILE_SHARE_READ | FILE_SHARE_WRITE

    Which means: the second call must at least share the same. So you must call

    TFileStream.Create('filename', fmOpenRead or fmShareDenyNone);
    

    ...if you want to succeed.

    Why does this make sense? Because when a third caller wants to open the file the OS does not maintain a chronological list of who opened it first and second, hence there is no "the first opener is more right than the second opener". If the second caller would reduce it from "share all" down to "share read" then why should a third caller adhere to that and not to the first caller's "share all" mode?