[Haskell-cafe] windows file locking

Bulat Ziganshin bulat.ziganshin at gmail.com
Sun Oct 15 12:53:36 EDT 2006

Hello Stefan,

Wednesday, October 11, 2006, 4:53:19 PM, you wrote:

> So far the windows API seems to work for me. Currently I'm still struggling to not
> write garbage to the file but the shared access works now. Does anyone have an
> example how to use it (e.g. the implementation of hPutStr on windows or something,
> i did not find it in the ghc source code)?

> I tried to use Streams before but without the windows API.

sorry, i'm a bit to fool you. there is a way to apply Handle API to
HANDLE. you should just

1) open file using win32 API and get HANDLE
2) convert this HANDLE to FD using _open_osfhandle from win32 api
3) open Handle over FD using fdToHandle function from GHC.Handle module

alternatively, you can use Streams with the same mechanism:

1) open file using win32 API and get HANDLE
2) convert this HANDLE to FD using _open_osfhandle from win32 api

  // it's in C language:
  fd = _open_osfhandle (someHANDLE, _O_TEXT | _O_WRONLY);

3) use bufferBlockStream to make full-featured Stream from this FD:

  do stream <- bufferBlockStream fd

it is from MS docs:


There are multiple types of file handles that can be opened using the Win32
API and the C Run-time:

   Returned Type  File Creation API      API Set
   HANDLE         CreateFile()           Win32
   HFILE          OpenFile()/_lcreat()   Win32
   int            _creat()/_open()       C Run-time
   FILE *         fopen()                C Run-time

In general, these file I/O "families" are incompatible with each other. On

some implementations of the Win32 application programming interfaces
(APIs), the OpenFile()/_lcreat() family of file I/O APIs are implemented as
"wrappers" around the CreateFile() family of file I/O APIs, meaning that
OpenFile(), _lcreat(), and _lopen() end up calling CreateFile(), returning
the handle returned by CreateFile(), and do not maintain any state
information about the file themselves. However, this is an implementation
detail only and is NOT a design feature.

NOTE: You cannot count on this being true on other implementations of the
Win32 APIs. Win32 file I/O APIs may be written using different methods on
other platforms, so reliance on this implementation detail may cause your
application to fail.

The rule to follow is to use one family of file I/O APIs and stick with
them--do not open a file with _lopen() and read from it with ReadFile(),
for example. This kind of incorrect use of the file I/O APIs can easily be
caught by the compiler, because the file types (HFILE and HANDLE

respectively) are incompatible with each other and the compiler will warn
you (at warning level /w3 or higher) when you have incorrectly passed one
type of file handle to a file I/O API that is expecting another, such as
passing an HFILE type to ReadFile(HANDLE, ...) in the above example.



The OpenFile() family of file I/O functions is provided only for
compatibility with earlier versions of Windows. New Win32-based
applications should use the CreateFile() family of file I/O APIs, which
provide added functionality that the earlier file I/O APIs do not provide.

Each of the two families of C Run-time file I/O APIs are incompatible with
any of the other file I/O families. It is incorrect to open a file handle
with one of the C Run-time file I/O APIs and operate on that file handle

with any other family of file I/O APIs, nor can a C Run-time file I/O
family operate on file handles opened by any other file I/O family.


For the C Run-time unbuffered I/O family of APIs [_open(), and so forth],
it is possible to extract the operating system handle that is associated
with that C run-time handle via the _get_osfhandle() C Run-time API. The
operating system handle is the handle stored in a C Run-time internal
structure associated with that C Run-time file handle. This operating

system handle is the handle that is returned from an operating system call
made by the C Run-time to open a file [CreateFile() in this case] when you
call one of the C Run-time unbuffered I/O APIs [_open(), _creat(),
_sopen(), and so forth].

The _get_osfhandle() C Run-time call is provided for informational purposes
only. Problems may occur if you read or write to the file using the
operating system handle returned from _get_osfhandle(); for these reasons
we recommend that you do not use the returned handle to read or write to

the file.


It is also possible to construct a C Run-time unbuffered file I/O handle
from an operating system handle [a CreateFile() handle] with the
_open_osfhandle() C Run-time API. In this case, the C Run-time uses the
existing operating system handle that you pass in rather than opening the
file itself. It is possible to use the original operating system handle to
read or write to the file, but it is very important that you use only the

original handle or the returned C Run-time handle to access the file, but
not both, because the C Run-time maintains state information that will not
be updated if you use the operating system handle to read or write to the

Best regards,
 Bulat                            mailto:Bulat.Ziganshin at gmail.com

More information about the Haskell-Cafe mailing list