You might think that if you want to get read/write access, you could pass STGM_READ | STGM_WRITE. You would be wrong. You have to pass STGM_READ­WRITE.

The three flags STGM_READ, STGM_WRITE, and STGM_READ­WRITE are mutually exclusive. If you try to combine them, you get a weird mess.

In particular, since the numerical value of STGM_READ is zero, passing STGM_READ | STGM_WRITE is numerically equivalent to passing STGM_WRITE, which grants write-only access.

The documentation for the STGM_* constants specifically says "It is not valid to use more than one element from a single group," and STGM_READ and STGM_WRITE belong to the Access group (as does STGM_READ­WRITE).

These values date back to the days of MS-DOS, where function 3Dh (Open File) passed an access mode in the AL register.

7 6 5 4 3 2 1 0
0 0 0 0 0 access
mode

The bottom three bits specified the requested access (0 = read-only, 1 = write-only, 2 = read/write), and the remaining bits were reserved.

Later, when networking support was added in approximately MS-DOS 3.5, three more bits were pressed into service:

7 6 5 4 3 2 1 0
0 share
mode
0 access
mode

Sharing modes were 0 = compatibility mode, 1 = deny all, 2 = deny write, 3 = deny read, 4 = deny none.

These values were carried forward into Windows as flags to the Open­File function:

Value Description
OF_READ
0x00000000
Opens a file for reading only.
OF_WRITE
0x00000001
Opens a file for write access only.
OF_READ­WRITE
0x00000002
Opens a file with read/write permissions.
OF_SHARE­COMPAT
0x00000000
Opens a file with compatibility mode, allows any process on a specified computer to open the file any number of times.
OF_SHARE­EXCLUSIVE
0x00000010
Opens a file with exclusive mode and denies both read/write ccess to other processes.
OF_SHARE­DENY­WRITE
0x00000020
Opens a file and denies write access to other processes.
OF_SHARE­DENY­READ
0x00000030
Opens a file and denies read access to other processes.
OF_SHARE­DENY­NONE
0x00000040
Opens a file without denying read or write access to other processes.

These flags were then carried forward into the STGM constants with the same numerical values.