Meaning of CF_OPEN_FILE_FLAG_FOREGROUND flag with CfOpenFileWithOplock

76 views Asked by At

The flag CF_OPEN_FILE_FLAG_FOREGROUND is not documented in either the documentation for CF_OPEN_FILE_FLAGS nor in the documentation for CfOpenFileWithOplock.

What is this flag's meaning?

1

There are 1 answers

0
Matt Smith On BEST ANSWER

The following information was supplied via a Microsoft Case:

CF_OPEN_FILE_FLAG_FOREGROUND is not documented, probably it was added at a later stage.

Based on the code, it seems that If a caller doesn’t want to use Oplocks, they should use this flag when calling CfOpenFileWithOplock. It implies that FILE_OPEN_REQUIRING_OPLOCK wouldn’t be set when the API calls CreateFile() underneath.

By default, the FOREGROUND flag is not specified, so the default behavior of CfOpenFileWithOplock is to request an oplock. That would make it consistent with defaulting to background behavior.

In this context “foreground” seems to mean that the caller is acting as a foreground application. I.e., they don’t care whether the file handle created by this API causes sharing violations for other callers, and they don’t care about breaking any oplocks that may already be on the file, so they open the handle without requesting an oplock. The default “background” behavior requests an oplock when opening the file handle so that their call fails if there’s already an oplock, and they can be told to close their handle if they need to get out of the way to avoid causing a sharing violation later.

Side note: unless the caller specifies CF_OPEN_FILE_FLAG_EXCLUSIVE to CfOpenFileWithOplock, the oplock they get will be only OPLOCK_LEVEL_CACHE_READ, not (OPLOCK_LEVEL_CACHE_READ | OPLOCK_LEVEL_CACHE_HANDLE), so there won’t be the sharing violation protection a background app might normally want.

Note: Microsoft has (since this case) has now documented this flag.

Further information was provided in this case, and is shared here as it is relevant in general to this API:

A background application typically wants to operate transparently on files. In particular, they want to avoid causing sharing violations to other (foreground) openers. To do that, they take a CACHE_READ | CACHE_HANDLE oplock, such as would be granted by using CF_OPEN_FILE_FLAG_EXCLUSIVE with CfOpenFileWithOplock. Then, if some other opener comes along whose requested share/access modes conflict with the background app’s, the background app’s oplock breaks. This prompts the background app to close their file handle (for a Cf handle, that causes it to become invalid – the real underlying handle has been closed). Once the background app closes their handle, the other opener’s open proceeds without hitting the sharing violation. That all works because of the CACHE_HANDLE part of the oplock. Without CF_OPEN_FILE_FLAG_EXCLUSIVE, the oplock only has CACHE_READ protection, so that sharing violation protection I described doesn’t happen.


  1. If CF_OPEN_FILE_FLAG_EXCLUSIVE is specified, the open is “share none” and it gets a CACHE_READ | CACHE_HANDLE oplock.
    a. A normal CreateFile call that opens for any of FILE_EXECUTE | FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE (or either/both of GENERIC_READ | GENERIC_WRITE) will break the oplock due to the sharing conflict, as described above. The oplock owner will get to finish and acknowledge.

  2. If CF_OPEN_FILE_FLAG_EXCLUSIVE is not specified, the open is “share all” and it gets a CACHE_READ oplock.

    a. A normal CreateFile call will not break the oplock.

    b. If the normal CreateFile specifies a sharing mode that conflicts with the Cf handle’s access (for instance, if the normal CreateFile does not specify FILE_SHARE_READ), the normal CreateFile will fail with ERROR_SHARING_VIOLATION.

    c. The oplock doesn’t break until the other caller issues a conflicting I/O, such as a write. When that happens the oplock break is advisory only.


The way the Cf APIs use oplocks, the “exclusive” oplock is the only one that breaks the way you’re expecting.

(i.e. a break that is not just advisory)