This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author eryksun
Recipients Carl Osterwisch, Gabi.Davar, John Florian, dabrahams, davide.rizzo, dlenski, eric.araujo, eric.smith, eryksun, jaraco, jwilk, martin.panter, ncoghlan, paul.moore, piotr.dobrogost, pitrou, r.david.murray, sbt, steve.dower, tim.golden, zach.ware
Date 2017-02-25.05:18:28
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1487999910.13.0.488525666876.issue14243@psf.upfronthosting.co.za>
In-reply-to
Content
Richard wrote:
> while a handle is open with share mode X, you can only reopen 
> the file if you also use share mode X

To clarify, the share mode is not a property of a handle. It's a property of a File object. A handle is a generic reference to any kind of kernel object, not just a File.

The following is a brief discussion about access sharing and the way file deletion works in Windows. Both of these tend to frustrate Unix programmers who end up supporting Windows. In this discussion, a "File", with an uppercase 'F', is the Windows kernel object type that references an open device or file-system directory, file, or stream. A "file", with a lowercase 'f', is a data file.

Shared access is implemented for File objects [1] and tracked in a SHARE_ACCESS record. When opening a file or directory, its shared access state is updated by the kernel function IoCheckShareAccess [2]. Discretionary shared access is primarily a concern for file systems, but volume devices and disk devices (e.g. \\.\C: and \\.\PhysicalDrive0) also use it. Devices that are flagged for mandatory exclusive access [3] (e.g. \\.\COM1) generally ignore the share mode. Some non-exclusive devices also ignore the share mode (e.g. \\.NUL and \\.CON). 

If it's not ignored, the share mode affects delete, write, read, and execute access. The following File access rights are affected: DELETE, FILE_WRITE_DATA, FILE_APPEND_DATA, FILE_READ_DATA, and FILE_EXECUTE. The share mode thus affects any combination of generic access -- GENERIC_ALL, GENERIC_WRITE, GENERIC_READ, GENERIC_EXECUTE. 

A File object's requested sharing is stored in its SharedDelete, SharedWrite, and SharedRead members. The granted access that's relevant to the share mode is stored in the DeleteAccess, WriteAccess (write/append), and ReadAccess (read/execute) members. Given these values, checking for a sharing violation and updating the shared access counts uses the following logic:

    RequireSharedDelete = DeleteAccessCount > 0;
    RequireSharedWrite = WriteAccessCount > 0;
    RequireSharedRead = ReadAccessCount > 0;
    DenyDeleteAccess = SharedDeleteCount < OpenCount;
    DenyWriteAccess = SharedWriteCount < OpenCount;
    DenyReadAccess = SharedReadCount < OpenCount;
    
    if (RequireSharedDelete && !SharedDelete ||
        RequireSharedWrite && !SharedWrite ||
        RequireSharedRead && !SharedRead ||
        DenyDeleteAccess && DeleteAccess ||
        DenyWriteAccess && WriteAccess ||
        DenyReadAccess && ReadAccess)
    {
        return STATUS_SHARING_VIOLATION;
    }

    OpenCount++;
    DeleteAccessCount += DeleteAccess;
    WriteAccessCount += WriteAccess;
    ReadAccessCount += ReadAccess;
    SharedDeleteCount += SharedDelete;
    SharedWriteCount += SharedWrite;
    SharedReadCount += SharedRead;

For example, to be granted delete access, all existing File object references must share delete access. However, if a file is opened with delete sharing but delete access hasn't been granted, then it can be opened again without delete sharing.

The SHARE_ACCESS structure is usually stored in a file (or stream) control block (FCB/SCB), which is a structure that coordinates access to a file or directory across multiple File objects. The FsContext member of a File object points at the FCB. 

A file system stores its private state for a File in a context control block (CCB), to which the File's FsContext2 member points. The CCB is where a file system tracks, for example, whether the file should be deleted when the object is closed. 

Deleting a file sets a delete disposition in the FCB/SCB (or LCB if hard links are supported). The file can't be unlinked until all referencing File objects have been closed and the underlying FCB/SCB/LCB is closing. Until then a 'deleted' file is still linked in the parent directory and prevents the directory from being deleted.

A deleted but still referenced file is in a semi-zombie state. Windows file systems don't allow opening such a file for any access, but it can still be accessed via existing objects. If one of these File objects has delete access, it can be used to unset the delete disposition (e.g. via SetFileInformationByHandle) to make the file accessible again.

[1]: https://msdn.microsoft.com/en-us/library/ff545834
[2]: https://msdn.microsoft.com/en-us/library/ff548341
[3]: https://msdn.microsoft.com/en-us/library/ff563827
History
Date User Action Args
2017-02-25 05:18:30eryksunsetrecipients: + eryksun, paul.moore, jaraco, ncoghlan, pitrou, eric.smith, tim.golden, jwilk, eric.araujo, r.david.murray, dabrahams, davide.rizzo, sbt, Gabi.Davar, martin.panter, piotr.dobrogost, zach.ware, dlenski, steve.dower, Carl Osterwisch, John Florian
2017-02-25 05:18:30eryksunsetmessageid: <1487999910.13.0.488525666876.issue14243@psf.upfronthosting.co.za>
2017-02-25 05:18:30eryksunlinkissue14243 messages
2017-02-25 05:18:28eryksuncreate