It seems to me that the best way to do this overall would be to have the FileStream closing only itself. It does not implicitly have knowledge of anything that exists in a layer above itself, so it is effectively an error for it to do anything that would affect those higher layers.
Having said that, the higher-level constructs should not axiomatically assume anything about any supplied underlying layer as well, or if they do so, they should do so explicitly:
1) If it was created from an existing stream, then the higher-level construct should be able to be closed INDEPENDENTLY of the underlying stream (effectively just disposing of any resources it allocated for its own use), or closed INCLUDING the underlying stream. These should be two distinct function calls, for example Close() and CloseSelf() (if this were to be implemented in such a way as to be backward compatible with existing code).
2) If it was not created from an existing stream (that is, the constructor had to create the underlying stream), then closing the higher-level construct should force the underlying stream to close as well, since in that case the underlying stream is an implicit part of the higher-level construct. In this case, CloseSelf() would simply call Close().
It seems wasteful to implement these classes the way it was done. If you plan to use the same file for (as an example) serial input and serial output, you are effectively forced by the system to treat it as two distinct entities if you wish to gain access to the higher level functionality of the descendant classes. Your alternative is to stick to the lower level construct and implement the higher-level functionality yourself - effectively re-implementing your own special versions of descendant classes that already exist.
If it were done as described above, the typical functionality would be as simple to implement as it is now, but for more sophisticated applications one would retain the ability to place a single lock on a file and re-purpose it as required when required as opposed to having to relinquish the lock and all associated resources and then instantly reallocate them all over again - adding overhead and memory fragmentation to the system without any valid reason.
Under the existing conditions, though, the correct thing is clear. The FileStream cannot be assumed to know anything about any object it becomes a part of, so you must close the outermost enclosing construct. This applies regardless of whether or not it works either way, as Bruno et al have noted, and for the reason they gave - compatibility. Assumption is the great-granddaddy of the ugliest bugs.