Sort entry points alphabetically.
[wine] / dlls / ntdll / file.c
1 /*
2  * Copyright 1999, 2000 Juergen Schmied
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 #include "config.h"
20 #include "wine/port.h"
21
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdio.h>
25 #include <errno.h>
26 #include <assert.h>
27 #ifdef HAVE_UNISTD_H
28 # include <unistd.h>
29 #endif
30 #ifdef HAVE_SYS_ERRNO_H
31 #include <sys/errno.h>
32 #endif
33 #ifdef HAVE_LINUX_MAJOR_H
34 # include <linux/major.h>
35 #endif
36 #ifdef HAVE_SYS_STATVFS_H
37 # include <sys/statvfs.h>
38 #endif
39 #ifdef HAVE_SYS_PARAM_H
40 # include <sys/param.h>
41 #endif
42 #ifdef HAVE_SYS_TIME_H
43 # include <sys/time.h>
44 #endif
45 #ifdef HAVE_UTIME_H
46 # include <utime.h>
47 #endif
48 #ifdef STATFS_DEFINED_BY_SYS_VFS
49 # include <sys/vfs.h>
50 #else
51 # ifdef STATFS_DEFINED_BY_SYS_MOUNT
52 #  include <sys/mount.h>
53 # else
54 #  ifdef STATFS_DEFINED_BY_SYS_STATFS
55 #   include <sys/statfs.h>
56 #  endif
57 # endif
58 #endif
59
60 #ifdef __APPLE__
61 # include <IOKit/IOKitLib.h>
62 # include <CoreFoundation/CFNumber.h> /* for kCFBooleanTrue, kCFBooleanFalse */
63 # include <paths.h>
64 #endif
65
66 #define NONAMELESSUNION
67 #define NONAMELESSSTRUCT
68 #include "wine/unicode.h"
69 #include "wine/debug.h"
70 #include "thread.h"
71 #include "wine/server.h"
72 #include "ntdll_misc.h"
73
74 #include "winternl.h"
75 #include "winioctl.h"
76
77 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
78
79 mode_t FILE_umask = 0;
80
81 #define SECSPERDAY         86400
82 #define SECS_1601_TO_1970  ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY)
83
84 /**************************************************************************
85  *                 NtOpenFile                           [NTDLL.@]
86  *                 ZwOpenFile                           [NTDLL.@]
87  *
88  * Open a file.
89  *
90  * PARAMS
91  *  handle    [O] Variable that receives the file handle on return
92  *  access    [I] Access desired by the caller to the file
93  *  attr      [I] Structure describing the file to be opened
94  *  io        [O] Receives details about the result of the operation
95  *  sharing   [I] Type of shared access the caller requires
96  *  options   [I] Options for the file open
97  *
98  * RETURNS
99  *  Success: 0. FileHandle and IoStatusBlock are updated.
100  *  Failure: An NTSTATUS error code describing the error.
101  */
102 NTSTATUS WINAPI NtOpenFile( PHANDLE handle, ACCESS_MASK access,
103                             POBJECT_ATTRIBUTES attr, PIO_STATUS_BLOCK io,
104                             ULONG sharing, ULONG options )
105 {
106     return NtCreateFile( handle, access, attr, io, NULL, 0,
107                          sharing, FILE_OPEN, options, NULL, 0 );
108 }
109
110 /**************************************************************************
111  *              NtCreateFile                            [NTDLL.@]
112  *              ZwCreateFile                            [NTDLL.@]
113  *
114  * Either create a new file or directory, or open an existing file, device,
115  * directory or volume.
116  *
117  * PARAMS
118  *      handle       [O] Points to a variable which receives the file handle on return
119  *      access       [I] Desired access to the file
120  *      attr         [I] Structure describing the file
121  *      io           [O] Receives information about the operation on return
122  *      alloc_size   [I] Initial size of the file in bytes
123  *      attributes   [I] Attributes to create the file with
124  *      sharing      [I] Type of shared access the caller would like to the file
125  *      disposition  [I] Specifies what to do, depending on whether the file already exists
126  *      options      [I] Options for creating a new file
127  *      ea_buffer    [I] Pointer to an extended attributes buffer
128  *      ea_length    [I] Length of ea_buffer
129  *
130  * RETURNS
131  *  Success: 0. handle and io are updated.
132  *  Failure: An NTSTATUS error code describing the error.
133  */
134 NTSTATUS WINAPI NtCreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATTRIBUTES attr,
135                               PIO_STATUS_BLOCK io, PLARGE_INTEGER alloc_size,
136                               ULONG attributes, ULONG sharing, ULONG disposition,
137                               ULONG options, PVOID ea_buffer, ULONG ea_length )
138 {
139     static const WCHAR pipeW[] = {'\\','?','?','\\','p','i','p','e','\\'};
140     static const WCHAR mailslotW[] = {'\\','?','?','\\','M','A','I','L','S','L','O','T','\\'};
141     ANSI_STRING unix_name;
142     int created = FALSE;
143
144     TRACE("handle=%p access=%08lx name=%s objattr=%08lx root=%p sec=%p io=%p alloc_size=%p\n"
145           "attr=%08lx sharing=%08lx disp=%ld options=%08lx ea=%p.0x%08lx\n",
146           handle, access, debugstr_us(attr->ObjectName), attr->Attributes,
147           attr->RootDirectory, attr->SecurityDescriptor, io, alloc_size,
148           attributes, sharing, disposition, options, ea_buffer, ea_length );
149
150     if (!attr || !attr->ObjectName) return STATUS_INVALID_PARAMETER;
151
152     if (attr->RootDirectory)
153     {
154         FIXME( "RootDirectory %p not supported\n", attr->RootDirectory );
155         return STATUS_OBJECT_NAME_NOT_FOUND;
156     }
157     if (alloc_size) FIXME( "alloc_size not supported\n" );
158
159     /* check for named pipe */
160
161     if (attr->ObjectName->Length > sizeof(pipeW) &&
162         !memicmpW( attr->ObjectName->Buffer, pipeW, sizeof(pipeW)/sizeof(WCHAR) ))
163     {
164         SERVER_START_REQ( open_named_pipe )
165         {
166             req->access = access;
167             req->flags = options;
168             req->inherit = (attr->Attributes & OBJ_INHERIT) != 0;
169             wine_server_add_data( req, attr->ObjectName->Buffer + 4,
170                                   attr->ObjectName->Length - 4*sizeof(WCHAR) );
171             io->u.Status = wine_server_call( req );
172             *handle = reply->handle;
173         }
174         SERVER_END_REQ;
175         return io->u.Status;
176     }
177
178     /* check for mailslot */
179
180     if (attr->ObjectName->Length > sizeof(mailslotW) &&
181         !memicmpW( attr->ObjectName->Buffer, mailslotW, sizeof(mailslotW)/sizeof(WCHAR) ))
182     {
183         SERVER_START_REQ( open_mailslot )
184         {
185             req->access = access & GENERIC_WRITE;
186             req->sharing = sharing;
187             req->inherit = (attr->Attributes & OBJ_INHERIT) != 0;
188             wine_server_add_data( req, attr->ObjectName->Buffer + 4,
189                                   attr->ObjectName->Length - 4*sizeof(WCHAR) );
190             io->u.Status = wine_server_call( req );
191             *handle = reply->handle;
192         }
193         SERVER_END_REQ;
194         return io->u.Status;
195     }
196
197     io->u.Status = wine_nt_to_unix_file_name( attr->ObjectName, &unix_name, disposition,
198                                               !(attr->Attributes & OBJ_CASE_INSENSITIVE) );
199
200     if (io->u.Status == STATUS_NO_SUCH_FILE &&
201         disposition != FILE_OPEN && disposition != FILE_OVERWRITE)
202     {
203         created = TRUE;
204         io->u.Status = STATUS_SUCCESS;
205     }
206
207     if (io->u.Status == STATUS_SUCCESS)
208     {
209         SERVER_START_REQ( create_file )
210         {
211             req->access     = access;
212             req->inherit    = (attr->Attributes & OBJ_INHERIT) != 0;
213             req->sharing    = sharing;
214             req->create     = disposition;
215             req->options    = options;
216             req->attrs      = attributes;
217             wine_server_add_data( req, unix_name.Buffer, unix_name.Length );
218             io->u.Status = wine_server_call( req );
219             *handle = reply->handle;
220         }
221         SERVER_END_REQ;
222         RtlFreeAnsiString( &unix_name );
223     }
224     else WARN("%s not found (%lx)\n", debugstr_us(attr->ObjectName), io->u.Status );
225
226     if (io->u.Status == STATUS_SUCCESS)
227     {
228         if (created) io->Information = FILE_CREATED;
229         else switch(disposition)
230         {
231         case FILE_SUPERSEDE:
232             io->Information = FILE_SUPERSEDED;
233             break;
234         case FILE_CREATE:
235             io->Information = FILE_CREATED;
236             break;
237         case FILE_OPEN:
238         case FILE_OPEN_IF:
239             io->Information = FILE_OPENED;
240             break;
241         case FILE_OVERWRITE:
242         case FILE_OVERWRITE_IF:
243             io->Information = FILE_OVERWRITTEN;
244             break;
245         }
246     }
247
248     return io->u.Status;
249 }
250
251 /***********************************************************************
252  *                  Asynchronous file I/O                              *
253  */
254 static void WINAPI FILE_AsyncReadService(void*, PIO_STATUS_BLOCK, ULONG);
255 static void WINAPI FILE_AsyncWriteService(void*, PIO_STATUS_BLOCK, ULONG);
256
257 typedef struct async_fileio
258 {
259     HANDLE              handle;
260     PIO_APC_ROUTINE     apc;
261     void*               apc_user;
262     char*               buffer;
263     unsigned int        count;
264     off_t               offset;
265     int                 queue_apc_on_error;
266     BOOL                avail_mode;
267     int                 fd;
268     HANDLE              event;
269 } async_fileio;
270
271 static void fileio_terminate(async_fileio *fileio, IO_STATUS_BLOCK* iosb)
272 {
273     TRACE("data: %p\n", fileio);
274
275     wine_server_release_fd( fileio->handle, fileio->fd );
276     if ( fileio->event != INVALID_HANDLE_VALUE )
277         NtSetEvent( fileio->event, NULL );
278
279     if (fileio->apc && 
280         (iosb->u.Status == STATUS_SUCCESS || fileio->queue_apc_on_error))
281         fileio->apc( fileio->apc_user, iosb, iosb->Information );
282
283     RtlFreeHeap( GetProcessHeap(), 0, fileio );
284 }
285
286
287 static ULONG fileio_queue_async(async_fileio* fileio, IO_STATUS_BLOCK* iosb, 
288                                 BOOL do_read)
289 {
290     PIO_APC_ROUTINE     apc = do_read ? FILE_AsyncReadService : FILE_AsyncWriteService;
291     NTSTATUS            status;
292
293     SERVER_START_REQ( register_async )
294     {
295         req->handle = fileio->handle;
296         req->io_apc = apc;
297         req->io_sb = iosb;
298         req->io_user = fileio;
299         req->type = do_read ? ASYNC_TYPE_READ : ASYNC_TYPE_WRITE;
300         req->count = (fileio->count < iosb->Information) ? 
301             0 : fileio->count - iosb->Information;
302         status = wine_server_call( req );
303     }
304     SERVER_END_REQ;
305
306     if ( status ) iosb->u.Status = status;
307     if ( iosb->u.Status != STATUS_PENDING )
308     {
309         (apc)( fileio, iosb, iosb->u.Status );
310         return iosb->u.Status;
311     }
312     NtCurrentTeb()->num_async_io++;
313     return STATUS_SUCCESS;
314 }
315
316 /***********************************************************************
317  *           FILE_GetNtStatus(void)
318  *
319  * Retrieve the Nt Status code from errno.
320  * Try to be consistent with FILE_SetDosError().
321  */
322 NTSTATUS FILE_GetNtStatus(void)
323 {
324     int err = errno;
325
326     TRACE( "errno = %d\n", errno );
327     switch (err)
328     {
329     case EAGAIN:    return STATUS_SHARING_VIOLATION;
330     case EBADF:     return STATUS_INVALID_HANDLE;
331     case ENOSPC:    return STATUS_DISK_FULL;
332     case EPERM:
333     case EROFS:
334     case EACCES:    return STATUS_ACCESS_DENIED;
335     case ENOTDIR:   return STATUS_OBJECT_PATH_NOT_FOUND;
336     case ENOENT:    return STATUS_OBJECT_NAME_NOT_FOUND;
337     case EISDIR:    return STATUS_FILE_IS_A_DIRECTORY;
338     case EMFILE:
339     case ENFILE:    return STATUS_TOO_MANY_OPENED_FILES;
340     case EINVAL:    return STATUS_INVALID_PARAMETER;
341     case ENOTEMPTY: return STATUS_DIRECTORY_NOT_EMPTY;
342     case EPIPE:     return STATUS_PIPE_BROKEN;
343     case EIO:       return STATUS_DEVICE_NOT_READY;
344 #ifdef ENOMEDIUM
345     case ENOMEDIUM: return STATUS_NO_MEDIA_IN_DEVICE;
346 #endif
347     case ENOTTY:
348     case EOPNOTSUPP:return STATUS_NOT_SUPPORTED;
349     case ECONNRESET:return STATUS_PIPE_DISCONNECTED;
350     case ENOEXEC:   /* ?? */
351     case ESPIPE:    /* ?? */
352     case EEXIST:    /* ?? */
353     default:
354         FIXME( "Converting errno %d to STATUS_UNSUCCESSFUL\n", err );
355         return STATUS_UNSUCCESSFUL;
356     }
357 }
358
359 /***********************************************************************
360  *             FILE_AsyncReadService      (INTERNAL)
361  *
362  *  This function is called while the client is waiting on the
363  *  server, so we can't make any server calls here.
364  */
365 static void WINAPI FILE_AsyncReadService(void *user, PIO_STATUS_BLOCK iosb, ULONG status)
366 {
367     async_fileio *fileio = (async_fileio*)user;
368     int result;
369     int already = iosb->Information;
370
371     TRACE("%p %p 0x%lx\n", iosb, fileio->buffer, status);
372
373     switch (status)
374     {
375     case STATUS_ALERTED: /* got some new data */
376         if (iosb->u.Status != STATUS_PENDING) FIXME("unexpected status %08lx\n", iosb->u.Status);
377         /* check to see if the data is ready (non-blocking) */
378         if ( fileio->avail_mode )
379             result = read(fileio->fd, &fileio->buffer[already], 
380                           fileio->count - already);
381         else
382         {
383             result = pread(fileio->fd, &fileio->buffer[already],
384                            fileio->count - already,
385                            fileio->offset + already);
386             if ((result < 0) && (errno == ESPIPE))
387                 result = read(fileio->fd, &fileio->buffer[already], 
388                               fileio->count - already);
389         }
390
391         if (result < 0)
392         {
393             if (errno == EAGAIN || errno == EINTR)
394             {
395                 TRACE("Deferred read %d\n", errno);
396                 iosb->u.Status = STATUS_PENDING;
397             }
398             else /* check to see if the transfer is complete */
399                 iosb->u.Status = FILE_GetNtStatus();
400         }
401         else if (result == 0)
402         {
403             iosb->u.Status = iosb->Information ? STATUS_SUCCESS : STATUS_END_OF_FILE;
404         }
405         else
406         {
407             iosb->Information += result;
408             if (iosb->Information >= fileio->count || fileio->avail_mode)
409                 iosb->u.Status = STATUS_SUCCESS;
410             else
411             {
412                 /* if we only have to read the available data, and none is available,
413                  * simply cancel the request. If data was available, it has been read
414                  * while in by previous call (NtDelayExecution)
415                  */
416                 iosb->u.Status = (fileio->avail_mode) ? STATUS_SUCCESS : STATUS_PENDING;
417             }
418
419             TRACE("read %d more bytes %ld/%d so far (%s)\n",
420                   result, iosb->Information, fileio->count, 
421                   (iosb->u.Status == STATUS_SUCCESS) ? "success" : "pending");
422         }
423         /* queue another async operation ? */
424         if (iosb->u.Status == STATUS_PENDING)
425             fileio_queue_async(fileio, iosb, TRUE);
426         else
427             fileio_terminate(fileio, iosb);
428         break;
429     default:
430         iosb->u.Status = status;
431         fileio_terminate(fileio, iosb);
432         break;
433     }
434 }
435
436
437 /******************************************************************************
438  *  NtReadFile                                  [NTDLL.@]
439  *  ZwReadFile                                  [NTDLL.@]
440  *
441  * Read from an open file handle.
442  *
443  * PARAMS
444  *  FileHandle    [I] Handle returned from ZwOpenFile() or ZwCreateFile()
445  *  Event         [I] Event to signal upon completion (or NULL)
446  *  ApcRoutine    [I] Callback to call upon completion (or NULL)
447  *  ApcContext    [I] Context for ApcRoutine (or NULL)
448  *  IoStatusBlock [O] Receives information about the operation on return
449  *  Buffer        [O] Destination for the data read
450  *  Length        [I] Size of Buffer
451  *  ByteOffset    [O] Destination for the new file pointer position (or NULL)
452  *  Key           [O] Function unknown (may be NULL)
453  *
454  * RETURNS
455  *  Success: 0. IoStatusBlock is updated, and the Information member contains
456  *           The number of bytes read.
457  *  Failure: An NTSTATUS error code describing the error.
458  */
459 NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
460                            PIO_APC_ROUTINE apc, void* apc_user,
461                            PIO_STATUS_BLOCK io_status, void* buffer, ULONG length,
462                            PLARGE_INTEGER offset, PULONG key)
463 {
464     int unix_handle, flags;
465
466     TRACE("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%p),partial stub!\n",
467           hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
468
469     if (!io_status) return STATUS_ACCESS_VIOLATION;
470
471     io_status->Information = 0;
472     io_status->u.Status = wine_server_handle_to_fd( hFile, GENERIC_READ, &unix_handle, &flags );
473     if (io_status->u.Status) return io_status->u.Status;
474
475     if (flags & FD_FLAG_RECV_SHUTDOWN)
476     {
477         wine_server_release_fd( hFile, unix_handle );
478         return STATUS_PIPE_DISCONNECTED;
479     }
480
481     if (flags & FD_FLAG_TIMEOUT)
482     {
483         if (hEvent)
484         {
485             /* this shouldn't happen, but check it */
486             FIXME("NIY-hEvent\n");
487             wine_server_release_fd( hFile, unix_handle );
488             return STATUS_NOT_IMPLEMENTED;
489         }
490         io_status->u.Status = NtCreateEvent(&hEvent, EVENT_ALL_ACCESS, NULL, 0, 0);
491         if (io_status->u.Status)
492         {
493             wine_server_release_fd( hFile, unix_handle );
494             return io_status->u.Status;
495         }
496     }
497
498     if (flags & (FD_FLAG_OVERLAPPED|FD_FLAG_TIMEOUT))
499     {
500         async_fileio*   fileio;
501         NTSTATUS ret;
502
503         if (!(fileio = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(async_fileio))))
504         {
505             wine_server_release_fd( hFile, unix_handle );
506             if (flags & FD_FLAG_TIMEOUT) NtClose(hEvent);
507             return STATUS_NO_MEMORY;
508         }
509         fileio->handle = hFile;
510         fileio->count = length;
511         if ( offset == NULL ) 
512             fileio->offset = 0;
513         else
514         {
515             fileio->offset = offset->QuadPart;
516             if (offset->u.HighPart && fileio->offset == offset->u.LowPart)
517                 FIXME("High part of offset is lost\n");
518         } 
519         fileio->apc = apc;
520         fileio->apc_user = apc_user;
521         fileio->buffer = buffer;
522         fileio->queue_apc_on_error = 0;
523         fileio->avail_mode = (flags & FD_FLAG_AVAILABLE);
524         fileio->fd = unix_handle;  /* FIXME */
525         fileio->event = hEvent;
526         NtResetEvent(hEvent, NULL);
527
528         io_status->u.Status = STATUS_PENDING;
529         ret = fileio_queue_async(fileio, io_status, TRUE);
530         if (ret != STATUS_SUCCESS)
531         {
532             wine_server_release_fd( hFile, unix_handle );
533             if (flags & FD_FLAG_TIMEOUT) NtClose(hEvent);
534             return ret;
535         }
536         if (flags & FD_FLAG_TIMEOUT)
537         {
538             ret = NtWaitForSingleObject(hEvent, TRUE, NULL);
539             NtClose(hEvent);
540             if (ret != STATUS_USER_APC)
541                 fileio->queue_apc_on_error = 1;
542         }
543         else
544         {
545             LARGE_INTEGER   timeout;
546
547             /* let some APC be run, this will read some already pending data */
548             timeout.u.LowPart = timeout.u.HighPart = 0;
549             ret = NtDelayExecution( TRUE, &timeout );
550             /* the apc didn't run and therefore the completion routine now
551              * needs to be sent errors.
552              * Note that there is no race between setting this flag and
553              * returning errors because apc's are run only during alertable
554              * waits */
555             if (ret != STATUS_USER_APC)
556                 fileio->queue_apc_on_error = 1;
557         }
558         TRACE("= 0x%08lx\n", io_status->u.Status);
559         return io_status->u.Status;
560     }
561
562     if (offset)
563     {
564         FILE_POSITION_INFORMATION   fpi;
565
566         fpi.CurrentByteOffset = *offset;
567         io_status->u.Status = NtSetInformationFile(hFile, io_status, &fpi, sizeof(fpi), 
568                                                    FilePositionInformation);
569         if (io_status->u.Status)
570         {
571             wine_server_release_fd( hFile, unix_handle );
572             return io_status->u.Status;
573         }
574     }
575     /* code for synchronous reads */
576     while ((io_status->Information = read( unix_handle, buffer, length )) == -1)
577     {
578         if ((errno == EAGAIN) || (errno == EINTR)) continue;
579         if (errno == EFAULT)
580         {
581             io_status->Information = 0;
582             io_status->u.Status = STATUS_ACCESS_VIOLATION;
583         }
584         else io_status->u.Status = FILE_GetNtStatus();
585         break;
586     }
587     wine_server_release_fd( hFile, unix_handle );
588     TRACE("= 0x%08lx\n", io_status->u.Status);
589     return io_status->u.Status;
590 }
591
592 /***********************************************************************
593  *             FILE_AsyncWriteService      (INTERNAL)
594  *
595  *  This function is called while the client is waiting on the
596  *  server, so we can't make any server calls here.
597  */
598 static void WINAPI FILE_AsyncWriteService(void *ovp, IO_STATUS_BLOCK *iosb, ULONG status)
599 {
600     async_fileio *fileio = (async_fileio *) ovp;
601     int result;
602     int already = iosb->Information;
603
604     TRACE("(%p %p 0x%lx)\n",iosb, fileio->buffer, status);
605
606     switch (status)
607     {
608     case STATUS_ALERTED:
609         /* write some data (non-blocking) */
610         if ( fileio->avail_mode )
611             result = write(fileio->fd, &fileio->buffer[already], 
612                            fileio->count - already);
613         else
614         {
615             result = pwrite(fileio->fd, &fileio->buffer[already], 
616                             fileio->count - already, fileio->offset + already);
617             if ((result < 0) && (errno == ESPIPE))
618                 result = write(fileio->fd, &fileio->buffer[already], 
619                                fileio->count - already);
620         }
621
622         if (result < 0)
623         {
624             if (errno == EAGAIN || errno == EINTR) iosb->u.Status = STATUS_PENDING;
625             else iosb->u.Status = FILE_GetNtStatus();
626         }
627         else
628         {
629             iosb->Information += result;
630             iosb->u.Status = (iosb->Information < fileio->count) ? STATUS_PENDING : STATUS_SUCCESS;
631             TRACE("wrote %d more bytes %ld/%d so far\n", 
632                   result, iosb->Information, fileio->count);
633         }
634         if (iosb->u.Status == STATUS_PENDING)
635             fileio_queue_async(fileio, iosb, FALSE);
636         else
637             fileio_terminate(fileio, iosb);
638         break;
639     default:
640         iosb->u.Status = status;
641         fileio_terminate(fileio, iosb);
642         break;
643     }
644 }
645
646 /******************************************************************************
647  *  NtWriteFile                                 [NTDLL.@]
648  *  ZwWriteFile                                 [NTDLL.@]
649  *
650  * Write to an open file handle.
651  *
652  * PARAMS
653  *  FileHandle    [I] Handle returned from ZwOpenFile() or ZwCreateFile()
654  *  Event         [I] Event to signal upon completion (or NULL)
655  *  ApcRoutine    [I] Callback to call upon completion (or NULL)
656  *  ApcContext    [I] Context for ApcRoutine (or NULL)
657  *  IoStatusBlock [O] Receives information about the operation on return
658  *  Buffer        [I] Source for the data to write
659  *  Length        [I] Size of Buffer
660  *  ByteOffset    [O] Destination for the new file pointer position (or NULL)
661  *  Key           [O] Function unknown (may be NULL)
662  *
663  * RETURNS
664  *  Success: 0. IoStatusBlock is updated, and the Information member contains
665  *           The number of bytes written.
666  *  Failure: An NTSTATUS error code describing the error.
667  */
668 NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
669                             PIO_APC_ROUTINE apc, void* apc_user,
670                             PIO_STATUS_BLOCK io_status, 
671                             const void* buffer, ULONG length,
672                             PLARGE_INTEGER offset, PULONG key)
673 {
674     int unix_handle, flags;
675
676     TRACE("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%p)!\n",
677           hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
678
679     if (!io_status) return STATUS_ACCESS_VIOLATION;
680
681     io_status->Information = 0;
682     io_status->u.Status = wine_server_handle_to_fd( hFile, GENERIC_WRITE, &unix_handle, &flags );
683     if (io_status->u.Status) return io_status->u.Status;
684
685     if (flags & FD_FLAG_SEND_SHUTDOWN)
686     {
687         wine_server_release_fd( hFile, unix_handle );
688         return STATUS_PIPE_DISCONNECTED;
689     }
690
691     if (flags & FD_FLAG_TIMEOUT)
692     {
693         if (hEvent)
694         {
695             /* this shouldn't happen, but check it */
696             FIXME("NIY-hEvent\n");
697             wine_server_release_fd( hFile, unix_handle );
698             return STATUS_NOT_IMPLEMENTED;
699         }
700         io_status->u.Status = NtCreateEvent(&hEvent, EVENT_ALL_ACCESS, NULL, 0, 0);
701         if (io_status->u.Status)
702         {
703             wine_server_release_fd( hFile, unix_handle );
704             return io_status->u.Status;
705         }
706     }
707
708     if (flags & (FD_FLAG_OVERLAPPED|FD_FLAG_TIMEOUT))
709     {
710         async_fileio*   fileio;
711         NTSTATUS ret;
712
713         if (!(fileio = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(async_fileio))))
714         {
715             wine_server_release_fd( hFile, unix_handle );
716             if (flags & FD_FLAG_TIMEOUT) NtClose(hEvent);
717             return STATUS_NO_MEMORY;
718         }
719         fileio->handle = hFile;
720         fileio->count = length;
721         if (offset)
722         {
723             fileio->offset = offset->QuadPart;
724             if (offset->u.HighPart && fileio->offset == offset->u.LowPart)
725                 FIXME("High part of offset is lost\n");
726         }
727         else  
728         {
729             fileio->offset = 0;
730         }
731         fileio->apc = apc;
732         fileio->apc_user = apc_user;
733         fileio->buffer = (void*)buffer;
734         fileio->queue_apc_on_error = 0;
735         fileio->avail_mode = (flags & FD_FLAG_AVAILABLE);
736         fileio->fd = unix_handle;  /* FIXME */
737         fileio->event = hEvent;
738         NtResetEvent(hEvent, NULL);
739
740         io_status->Information = 0;
741         io_status->u.Status = STATUS_PENDING;
742         ret = fileio_queue_async(fileio, io_status, FALSE);
743         if (ret != STATUS_SUCCESS)
744         {
745             wine_server_release_fd( hFile, unix_handle );
746             if (flags & FD_FLAG_TIMEOUT) NtClose(hEvent);
747             return ret;
748         }
749         if (flags & FD_FLAG_TIMEOUT)
750         {
751             ret = NtWaitForSingleObject(hEvent, TRUE, NULL);
752             NtClose(hEvent);
753             if (ret != STATUS_USER_APC)
754                 fileio->queue_apc_on_error = 1;
755         }
756         else
757         {
758             LARGE_INTEGER   timeout;
759
760             /* let some APC be run, this will write as much data as possible */
761             timeout.u.LowPart = timeout.u.HighPart = 0;
762             ret = NtDelayExecution( TRUE, &timeout );
763             /* the apc didn't run and therefore the completion routine now
764              * needs to be sent errors.
765              * Note that there is no race between setting this flag and
766              * returning errors because apc's are run only during alertable
767              * waits */
768             if (ret != STATUS_USER_APC)
769                 fileio->queue_apc_on_error = 1;
770         }
771         return io_status->u.Status;
772     }
773
774     if (offset)
775     {
776         FILE_POSITION_INFORMATION   fpi;
777
778         fpi.CurrentByteOffset = *offset;
779         io_status->u.Status = NtSetInformationFile(hFile, io_status, &fpi, sizeof(fpi),
780                                                    FilePositionInformation);
781         if (io_status->u.Status)
782         {
783             wine_server_release_fd( hFile, unix_handle );
784             return io_status->u.Status;
785         }
786     }
787
788     /* synchronous file write */
789     while ((io_status->Information = write( unix_handle, buffer, length )) == -1)
790     {
791         if ((errno == EAGAIN) || (errno == EINTR)) continue;
792         if (errno == EFAULT)
793         {
794             io_status->Information = 0;
795             io_status->u.Status = STATUS_INVALID_USER_BUFFER;
796         }
797         else if (errno == ENOSPC) io_status->u.Status = STATUS_DISK_FULL;
798         else io_status->u.Status = FILE_GetNtStatus();
799         break;
800     }
801     wine_server_release_fd( hFile, unix_handle );
802     return io_status->u.Status;
803 }
804
805 /**************************************************************************
806  *              NtDeviceIoControlFile                   [NTDLL.@]
807  *              ZwDeviceIoControlFile                   [NTDLL.@]
808  *
809  * Perform an I/O control operation on an open file handle.
810  *
811  * PARAMS
812  *  DeviceHandle     [I] Handle returned from ZwOpenFile() or ZwCreateFile()
813  *  Event            [I] Event to signal upon completion (or NULL)
814  *  ApcRoutine       [I] Callback to call upon completion (or NULL)
815  *  ApcContext       [I] Context for ApcRoutine (or NULL)
816  *  IoStatusBlock    [O] Receives information about the operation on return
817  *  IoControlCode    [I] Control code for the operation to perform
818  *  InputBuffer      [I] Source for any input data required (or NULL)
819  *  InputBufferSize  [I] Size of InputBuffer
820  *  OutputBuffer     [O] Source for any output data returned (or NULL)
821  *  OutputBufferSize [I] Size of OutputBuffer
822  *
823  * RETURNS
824  *  Success: 0. IoStatusBlock is updated.
825  *  Failure: An NTSTATUS error code describing the error.
826  */
827 NTSTATUS WINAPI NtDeviceIoControlFile(HANDLE DeviceHandle, HANDLE hEvent,
828                                       PIO_APC_ROUTINE UserApcRoutine, 
829                                       PVOID UserApcContext,
830                                       PIO_STATUS_BLOCK IoStatusBlock,
831                                       ULONG IoControlCode,
832                                       PVOID InputBuffer,
833                                       ULONG InputBufferSize,
834                                       PVOID OutputBuffer,
835                                       ULONG OutputBufferSize)
836 {
837     TRACE("(%p,%p,%p,%p,%p,0x%08lx,%p,0x%08lx,%p,0x%08lx)\n",
838           DeviceHandle, hEvent, UserApcRoutine, UserApcContext,
839           IoStatusBlock, IoControlCode, 
840           InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize);
841
842     if (CDROM_DeviceIoControl(DeviceHandle, hEvent,
843                               UserApcRoutine, UserApcContext,
844                               IoStatusBlock, IoControlCode,
845                               InputBuffer, InputBufferSize,
846                               OutputBuffer, OutputBufferSize) == STATUS_NO_SUCH_DEVICE)
847     {
848         /* it wasn't a CDROM */
849         FIXME("Unimplemented dwIoControlCode=%08lx\n", IoControlCode);
850         IoStatusBlock->u.Status = STATUS_NOT_IMPLEMENTED;
851         IoStatusBlock->Information = 0;
852         if (hEvent) NtSetEvent(hEvent, NULL);
853     }
854     return IoStatusBlock->u.Status;
855 }
856
857 /******************************************************************************
858  * NtFsControlFile [NTDLL.@]
859  * ZwFsControlFile [NTDLL.@]
860  */
861 NTSTATUS WINAPI NtFsControlFile(
862         IN HANDLE DeviceHandle,
863         IN HANDLE Event OPTIONAL,
864         IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
865         IN PVOID ApcContext OPTIONAL,
866         OUT PIO_STATUS_BLOCK IoStatusBlock,
867         IN ULONG IoControlCode,
868         IN PVOID InputBuffer,
869         IN ULONG InputBufferSize,
870         OUT PVOID OutputBuffer,
871         IN ULONG OutputBufferSize)
872 {
873         FIXME("(%p,%p,%p,%p,%p,0x%08lx,%p,0x%08lx,%p,0x%08lx): stub\n",
874         DeviceHandle,Event,ApcRoutine,ApcContext,IoStatusBlock,IoControlCode,
875         InputBuffer,InputBufferSize,OutputBuffer,OutputBufferSize);
876         return 0;
877 }
878
879 /******************************************************************************
880  *  NtSetVolumeInformationFile          [NTDLL.@]
881  *  ZwSetVolumeInformationFile          [NTDLL.@]
882  *
883  * Set volume information for an open file handle.
884  *
885  * PARAMS
886  *  FileHandle         [I] Handle returned from ZwOpenFile() or ZwCreateFile()
887  *  IoStatusBlock      [O] Receives information about the operation on return
888  *  FsInformation      [I] Source for volume information
889  *  Length             [I] Size of FsInformation
890  *  FsInformationClass [I] Type of volume information to set
891  *
892  * RETURNS
893  *  Success: 0. IoStatusBlock is updated.
894  *  Failure: An NTSTATUS error code describing the error.
895  */
896 NTSTATUS WINAPI NtSetVolumeInformationFile(
897         IN HANDLE FileHandle,
898         PIO_STATUS_BLOCK IoStatusBlock,
899         PVOID FsInformation,
900         ULONG Length,
901         FS_INFORMATION_CLASS FsInformationClass)
902 {
903         FIXME("(%p,%p,%p,0x%08lx,0x%08x) stub\n",
904         FileHandle,IoStatusBlock,FsInformation,Length,FsInformationClass);
905         return 0;
906 }
907
908 /******************************************************************************
909  *  NtQueryInformationFile              [NTDLL.@]
910  *  ZwQueryInformationFile              [NTDLL.@]
911  *
912  * Get information about an open file handle.
913  *
914  * PARAMS
915  *  hFile    [I] Handle returned from ZwOpenFile() or ZwCreateFile()
916  *  io       [O] Receives information about the operation on return
917  *  ptr      [O] Destination for file information
918  *  len      [I] Size of FileInformation
919  *  class    [I] Type of file information to get
920  *
921  * RETURNS
922  *  Success: 0. IoStatusBlock and FileInformation are updated.
923  *  Failure: An NTSTATUS error code describing the error.
924  */
925 NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
926                                         PVOID ptr, LONG len, FILE_INFORMATION_CLASS class )
927 {
928     static const size_t info_sizes[] =
929     {
930         0,
931         sizeof(FILE_DIRECTORY_INFORMATION),            /* FileDirectoryInformation */
932         sizeof(FILE_FULL_DIRECTORY_INFORMATION),       /* FileFullDirectoryInformation */
933         sizeof(FILE_BOTH_DIRECTORY_INFORMATION),       /* FileBothDirectoryInformation */
934         sizeof(FILE_BASIC_INFORMATION),                /* FileBasicInformation */
935         sizeof(FILE_STANDARD_INFORMATION),             /* FileStandardInformation */
936         sizeof(FILE_INTERNAL_INFORMATION),             /* FileInternalInformation */
937         sizeof(FILE_EA_INFORMATION),                   /* FileEaInformation */
938         sizeof(FILE_ACCESS_INFORMATION),               /* FileAccessInformation */
939         sizeof(FILE_NAME_INFORMATION)-sizeof(WCHAR),   /* FileNameInformation */
940         sizeof(FILE_RENAME_INFORMATION)-sizeof(WCHAR), /* FileRenameInformation */
941         0,                                             /* FileLinkInformation */
942         sizeof(FILE_NAMES_INFORMATION)-sizeof(WCHAR),  /* FileNamesInformation */
943         sizeof(FILE_DISPOSITION_INFORMATION),          /* FileDispositionInformation */
944         sizeof(FILE_POSITION_INFORMATION),             /* FilePositionInformation */
945         sizeof(FILE_FULL_EA_INFORMATION),              /* FileFullEaInformation */
946         sizeof(FILE_MODE_INFORMATION),                 /* FileModeInformation */
947         sizeof(FILE_ALIGNMENT_INFORMATION),            /* FileAlignmentInformation */
948         sizeof(FILE_ALL_INFORMATION)-sizeof(WCHAR),    /* FileAllInformation */
949         sizeof(FILE_ALLOCATION_INFORMATION),           /* FileAllocationInformation */
950         sizeof(FILE_END_OF_FILE_INFORMATION),          /* FileEndOfFileInformation */
951         0,                                             /* FileAlternateNameInformation */
952         sizeof(FILE_STREAM_INFORMATION)-sizeof(WCHAR), /* FileStreamInformation */
953         0,                                             /* FilePipeInformation */
954         0,                                             /* FilePipeLocalInformation */
955         0,                                             /* FilePipeRemoteInformation */
956         sizeof(FILE_MAILSLOT_QUERY_INFORMATION),       /* FileMailslotQueryInformation */
957         0,                                             /* FileMailslotSetInformation */
958         0,                                             /* FileCompressionInformation */
959         0,                                             /* FileObjectIdInformation */
960         0,                                             /* FileCompletionInformation */
961         0,                                             /* FileMoveClusterInformation */
962         0,                                             /* FileQuotaInformation */
963         0,                                             /* FileReparsePointInformation */
964         0,                                             /* FileNetworkOpenInformation */
965         0,                                             /* FileAttributeTagInformation */
966         0                                              /* FileTrackingInformation */
967     };
968
969     struct stat st;
970     int fd;
971
972     TRACE("(%p,%p,%p,0x%08lx,0x%08x)\n", hFile, io, ptr, len, class);
973
974     io->Information = 0;
975
976     if (class <= 0 || class >= FileMaximumInformation)
977         return io->u.Status = STATUS_INVALID_INFO_CLASS;
978     if (!info_sizes[class])
979     {
980         FIXME("Unsupported class (%d)\n", class);
981         return io->u.Status = STATUS_NOT_IMPLEMENTED;
982     }
983     if (len < info_sizes[class])
984         return io->u.Status = STATUS_INFO_LENGTH_MISMATCH;
985
986     if ((io->u.Status = wine_server_handle_to_fd( hFile, 0, &fd, NULL )))
987         return io->u.Status;
988
989     switch (class)
990     {
991     case FileBasicInformation:
992         {
993             FILE_BASIC_INFORMATION *info = ptr;
994
995             if (fstat( fd, &st ) == -1)
996                 io->u.Status = FILE_GetNtStatus();
997             else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
998                 io->u.Status = STATUS_INVALID_INFO_CLASS;
999             else
1000             {
1001                 if (S_ISDIR(st.st_mode)) info->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
1002                 else info->FileAttributes = FILE_ATTRIBUTE_ARCHIVE;
1003                 if (!(st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
1004                     info->FileAttributes |= FILE_ATTRIBUTE_READONLY;
1005                 RtlSecondsSince1970ToTime( st.st_mtime, &info->CreationTime);
1006                 RtlSecondsSince1970ToTime( st.st_mtime, &info->LastWriteTime);
1007                 RtlSecondsSince1970ToTime( st.st_ctime, &info->ChangeTime);
1008                 RtlSecondsSince1970ToTime( st.st_atime, &info->LastAccessTime);
1009             }
1010         }
1011         break;
1012     case FileStandardInformation:
1013         {
1014             FILE_STANDARD_INFORMATION *info = ptr;
1015
1016             if (fstat( fd, &st ) == -1) io->u.Status = FILE_GetNtStatus();
1017             else
1018             {
1019                 if ((info->Directory = S_ISDIR(st.st_mode)))
1020                 {
1021                     info->AllocationSize.QuadPart = 0;
1022                     info->EndOfFile.QuadPart      = 0;
1023                     info->NumberOfLinks           = 1;
1024                     info->DeletePending           = FALSE;
1025                 }
1026                 else
1027                 {
1028                     info->AllocationSize.QuadPart = (ULONGLONG)st.st_blocks * 512;
1029                     info->EndOfFile.QuadPart      = st.st_size;
1030                     info->NumberOfLinks           = st.st_nlink;
1031                     info->DeletePending           = FALSE; /* FIXME */
1032                 }
1033             }
1034         }
1035         break;
1036     case FilePositionInformation:
1037         {
1038             FILE_POSITION_INFORMATION *info = ptr;
1039             off_t res = lseek( fd, 0, SEEK_CUR );
1040             if (res == (off_t)-1) io->u.Status = FILE_GetNtStatus();
1041             else info->CurrentByteOffset.QuadPart = res;
1042         }
1043         break;
1044     case FileInternalInformation:
1045         {
1046             FILE_INTERNAL_INFORMATION *info = ptr;
1047
1048             if (fstat( fd, &st ) == -1) io->u.Status = FILE_GetNtStatus();
1049             else info->IndexNumber.QuadPart = st.st_ino;
1050         }
1051         break;
1052     case FileEaInformation:
1053         {
1054             FILE_EA_INFORMATION *info = ptr;
1055             info->EaSize = 0;
1056         }
1057         break;
1058     case FileEndOfFileInformation:
1059         {
1060             FILE_END_OF_FILE_INFORMATION *info = ptr;
1061
1062             if (fstat( fd, &st ) == -1) io->u.Status = FILE_GetNtStatus();
1063             else info->EndOfFile.QuadPart = S_ISDIR(st.st_mode) ? 0 : st.st_size;
1064         }
1065         break;
1066     case FileAllInformation:
1067         {
1068             FILE_ALL_INFORMATION *info = ptr;
1069
1070             if (fstat( fd, &st ) == -1) io->u.Status = FILE_GetNtStatus();
1071             else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
1072                 io->u.Status = STATUS_INVALID_INFO_CLASS;
1073             else
1074             {
1075                 if ((info->StandardInformation.Directory = S_ISDIR(st.st_mode)))
1076                 {
1077                     info->BasicInformation.FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
1078                     info->StandardInformation.AllocationSize.QuadPart = 0;
1079                     info->StandardInformation.EndOfFile.QuadPart      = 0;
1080                     info->StandardInformation.NumberOfLinks           = 1;
1081                     info->StandardInformation.DeletePending           = FALSE;
1082                 }
1083                 else
1084                 {
1085                     info->BasicInformation.FileAttributes = FILE_ATTRIBUTE_ARCHIVE;
1086                     info->StandardInformation.AllocationSize.QuadPart = (ULONGLONG)st.st_blocks * 512;
1087                     info->StandardInformation.EndOfFile.QuadPart      = st.st_size;
1088                     info->StandardInformation.NumberOfLinks           = st.st_nlink;
1089                     info->StandardInformation.DeletePending           = FALSE; /* FIXME */
1090                 }
1091                 if (!(st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
1092                     info->BasicInformation.FileAttributes |= FILE_ATTRIBUTE_READONLY;
1093                 RtlSecondsSince1970ToTime( st.st_mtime, &info->BasicInformation.CreationTime);
1094                 RtlSecondsSince1970ToTime( st.st_mtime, &info->BasicInformation.LastWriteTime);
1095                 RtlSecondsSince1970ToTime( st.st_ctime, &info->BasicInformation.ChangeTime);
1096                 RtlSecondsSince1970ToTime( st.st_atime, &info->BasicInformation.LastAccessTime);
1097                 info->InternalInformation.IndexNumber.QuadPart = st.st_ino;
1098                 info->EaInformation.EaSize = 0;
1099                 info->AccessInformation.AccessFlags = 0;  /* FIXME */
1100                 info->PositionInformation.CurrentByteOffset.QuadPart = lseek( fd, 0, SEEK_CUR );
1101                 info->ModeInformation.Mode = 0;  /* FIXME */
1102                 info->AlignmentInformation.AlignmentRequirement = 1;  /* FIXME */
1103                 info->NameInformation.FileNameLength = 0;
1104                 io->Information = sizeof(*info) - sizeof(WCHAR);
1105             }
1106         }
1107         break;
1108     case FileMailslotQueryInformation:
1109         {
1110             FILE_MAILSLOT_QUERY_INFORMATION *info = ptr;
1111
1112             SERVER_START_REQ( set_mailslot_info )
1113             {
1114                 req->handle = hFile;
1115                 req->flags = 0;
1116                 io->u.Status = wine_server_call( req );
1117                 if( io->u.Status == STATUS_SUCCESS )
1118                 {
1119                     info->MaximumMessageSize = reply->max_msgsize;
1120                     info->MailslotQuota = 0;
1121                     info->NextMessageSize = reply->next_msgsize;
1122                     info->MessagesAvailable = reply->msg_count;
1123                     info->ReadTimeout.QuadPart = reply->read_timeout * -10000;
1124                 }
1125             }
1126             SERVER_END_REQ;
1127         }
1128         break;
1129     default:
1130         FIXME("Unsupported class (%d)\n", class);
1131         io->u.Status = STATUS_NOT_IMPLEMENTED;
1132         break;
1133     }
1134     wine_server_release_fd( hFile, fd );
1135     if (io->u.Status == STATUS_SUCCESS && !io->Information) io->Information = info_sizes[class];
1136     return io->u.Status;
1137 }
1138
1139 /******************************************************************************
1140  *  NtSetInformationFile                [NTDLL.@]
1141  *  ZwSetInformationFile                [NTDLL.@]
1142  *
1143  * Set information about an open file handle.
1144  *
1145  * PARAMS
1146  *  handle  [I] Handle returned from ZwOpenFile() or ZwCreateFile()
1147  *  io      [O] Receives information about the operation on return
1148  *  ptr     [I] Source for file information
1149  *  len     [I] Size of FileInformation
1150  *  class   [I] Type of file information to set
1151  *
1152  * RETURNS
1153  *  Success: 0. io is updated.
1154  *  Failure: An NTSTATUS error code describing the error.
1155  */
1156 NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io,
1157                                      PVOID ptr, ULONG len, FILE_INFORMATION_CLASS class)
1158 {
1159     int fd;
1160
1161     TRACE("(%p,%p,%p,0x%08lx,0x%08x)\n", handle, io, ptr, len, class);
1162
1163     if ((io->u.Status = wine_server_handle_to_fd( handle, 0, &fd, NULL )))
1164         return io->u.Status;
1165
1166     io->u.Status = STATUS_SUCCESS;
1167     switch (class)
1168     {
1169     case FileBasicInformation:
1170         if (len >= sizeof(FILE_BASIC_INFORMATION))
1171         {
1172             struct stat st;
1173             const FILE_BASIC_INFORMATION *info = ptr;
1174
1175             if (info->LastAccessTime.QuadPart || info->LastWriteTime.QuadPart)
1176             {
1177                 ULONGLONG sec, nsec;
1178                 struct timeval tv[2];
1179
1180                 if (!info->LastAccessTime.QuadPart || !info->LastWriteTime.QuadPart)
1181                 {
1182
1183                     tv[0].tv_sec = tv[0].tv_usec = 0;
1184                     tv[1].tv_sec = tv[1].tv_usec = 0;
1185                     if (!fstat( fd, &st ))
1186                     {
1187                         tv[0].tv_sec = st.st_atime;
1188                         tv[1].tv_sec = st.st_mtime;
1189                     }
1190                 }
1191                 if (info->LastAccessTime.QuadPart)
1192                 {
1193                     sec = RtlLargeIntegerDivide( info->LastAccessTime.QuadPart, 10000000, &nsec );
1194                     tv[0].tv_sec = sec - SECS_1601_TO_1970;
1195                     tv[0].tv_usec = (UINT)nsec / 10;
1196                 }
1197                 if (info->LastWriteTime.QuadPart)
1198                 {
1199                     sec = RtlLargeIntegerDivide( info->LastWriteTime.QuadPart, 10000000, &nsec );
1200                     tv[1].tv_sec = sec - SECS_1601_TO_1970;
1201                     tv[1].tv_usec = (UINT)nsec / 10;
1202                 }
1203                 if (futimes( fd, tv ) == -1) io->u.Status = FILE_GetNtStatus();
1204             }
1205
1206             if (io->u.Status == STATUS_SUCCESS && info->FileAttributes)
1207             {
1208                 if (fstat( fd, &st ) == -1) io->u.Status = FILE_GetNtStatus();
1209                 else
1210                 {
1211                     if (info->FileAttributes & FILE_ATTRIBUTE_READONLY)
1212                     {
1213                         if (S_ISDIR( st.st_mode))
1214                             WARN("FILE_ATTRIBUTE_READONLY ignored for directory.\n");
1215                         else
1216                             st.st_mode &= ~0222; /* clear write permission bits */
1217                     }
1218                     else
1219                     {
1220                         /* add write permission only where we already have read permission */
1221                         st.st_mode |= (0600 | ((st.st_mode & 044) >> 1)) & (~FILE_umask);
1222                     }
1223                     if (fchmod( fd, st.st_mode ) == -1) io->u.Status = FILE_GetNtStatus();
1224                 }
1225             }
1226         }
1227         else io->u.Status = STATUS_INVALID_PARAMETER_3;
1228         break;
1229
1230     case FilePositionInformation:
1231         if (len >= sizeof(FILE_POSITION_INFORMATION))
1232         {
1233             const FILE_POSITION_INFORMATION *info = ptr;
1234
1235             if (lseek( fd, info->CurrentByteOffset.QuadPart, SEEK_SET ) == (off_t)-1)
1236                 io->u.Status = FILE_GetNtStatus();
1237         }
1238         else io->u.Status = STATUS_INVALID_PARAMETER_3;
1239         break;
1240
1241     case FileEndOfFileInformation:
1242         if (len >= sizeof(FILE_END_OF_FILE_INFORMATION))
1243         {
1244             struct stat st;
1245             const FILE_END_OF_FILE_INFORMATION *info = ptr;
1246
1247             /* first try normal truncate */
1248             if (ftruncate( fd, (off_t)info->EndOfFile.QuadPart ) != -1) break;
1249
1250             /* now check for the need to extend the file */
1251             if (fstat( fd, &st ) != -1 && (off_t)info->EndOfFile.QuadPart > st.st_size)
1252             {
1253                 static const char zero;
1254
1255                 /* extend the file one byte beyond the requested size and then truncate it */
1256                 /* this should work around ftruncate implementations that can't extend files */
1257                 if (pwrite( fd, &zero, 1, (off_t)info->EndOfFile.QuadPart ) != -1 &&
1258                     ftruncate( fd, (off_t)info->EndOfFile.QuadPart ) != -1) break;
1259             }
1260             io->u.Status = FILE_GetNtStatus();
1261         }
1262         else io->u.Status = STATUS_INVALID_PARAMETER_3;
1263         break;
1264
1265     case FileMailslotSetInformation:
1266         {
1267             FILE_MAILSLOT_SET_INFORMATION *info = ptr;
1268
1269             SERVER_START_REQ( set_mailslot_info )
1270             {
1271                 req->handle = handle;
1272                 req->flags = MAILSLOT_SET_READ_TIMEOUT;
1273                 req->read_timeout = info->ReadTimeout.QuadPart / -10000;
1274                 io->u.Status = wine_server_call( req );
1275             }
1276             SERVER_END_REQ;
1277         }
1278         break;
1279
1280     default:
1281         FIXME("Unsupported class (%d)\n", class);
1282         io->u.Status = STATUS_NOT_IMPLEMENTED;
1283         break;
1284     }
1285     wine_server_release_fd( handle, fd );
1286     io->Information = 0;
1287     return io->u.Status;
1288 }
1289
1290
1291 /******************************************************************************
1292  *              NtQueryFullAttributesFile   (NTDLL.@)
1293  */
1294 NTSTATUS WINAPI NtQueryFullAttributesFile( const OBJECT_ATTRIBUTES *attr,
1295                                            FILE_NETWORK_OPEN_INFORMATION *info )
1296 {
1297     ANSI_STRING unix_name;
1298     NTSTATUS status;
1299
1300     if (!(status = wine_nt_to_unix_file_name( attr->ObjectName, &unix_name, FILE_OPEN,
1301                                               !(attr->Attributes & OBJ_CASE_INSENSITIVE) )))
1302     {
1303         struct stat st;
1304
1305         if (stat( unix_name.Buffer, &st ) == -1)
1306             status = FILE_GetNtStatus();
1307         else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
1308             status = STATUS_INVALID_INFO_CLASS;
1309         else
1310         {
1311             if (S_ISDIR(st.st_mode))
1312             {
1313                 info->FileAttributes          = FILE_ATTRIBUTE_DIRECTORY;
1314                 info->AllocationSize.QuadPart = 0;
1315                 info->EndOfFile.QuadPart      = 0;
1316             }
1317             else
1318             {
1319                 info->FileAttributes          = FILE_ATTRIBUTE_ARCHIVE;
1320                 info->AllocationSize.QuadPart = (ULONGLONG)st.st_blocks * 512;
1321                 info->EndOfFile.QuadPart      = st.st_size;
1322             }
1323             if (!(st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
1324                 info->FileAttributes |= FILE_ATTRIBUTE_READONLY;
1325             RtlSecondsSince1970ToTime( st.st_mtime, &info->CreationTime );
1326             RtlSecondsSince1970ToTime( st.st_mtime, &info->LastWriteTime );
1327             RtlSecondsSince1970ToTime( st.st_ctime, &info->ChangeTime );
1328             RtlSecondsSince1970ToTime( st.st_atime, &info->LastAccessTime );
1329             if (DIR_is_hidden_file( attr->ObjectName ))
1330                 info->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
1331         }
1332         RtlFreeAnsiString( &unix_name );
1333     }
1334     else WARN("%s not found (%lx)\n", debugstr_us(attr->ObjectName), status );
1335     return status;
1336 }
1337
1338
1339 /******************************************************************************
1340  *              NtQueryAttributesFile   (NTDLL.@)
1341  *              ZwQueryAttributesFile   (NTDLL.@)
1342  */
1343 NTSTATUS WINAPI NtQueryAttributesFile( const OBJECT_ATTRIBUTES *attr, FILE_BASIC_INFORMATION *info )
1344 {
1345     FILE_NETWORK_OPEN_INFORMATION full_info;
1346     NTSTATUS status;
1347
1348     if (!(status = NtQueryFullAttributesFile( attr, &full_info )))
1349     {
1350         info->CreationTime.QuadPart   = full_info.CreationTime.QuadPart;
1351         info->LastAccessTime.QuadPart = full_info.LastAccessTime.QuadPart;
1352         info->LastWriteTime.QuadPart  = full_info.LastWriteTime.QuadPart;
1353         info->ChangeTime.QuadPart     = full_info.ChangeTime.QuadPart;
1354         info->FileAttributes          = full_info.FileAttributes;
1355     }
1356     return status;
1357 }
1358
1359
1360 /******************************************************************************
1361  *  NtQueryVolumeInformationFile                [NTDLL.@]
1362  *  ZwQueryVolumeInformationFile                [NTDLL.@]
1363  *
1364  * Get volume information for an open file handle.
1365  *
1366  * PARAMS
1367  *  handle      [I] Handle returned from ZwOpenFile() or ZwCreateFile()
1368  *  io          [O] Receives information about the operation on return
1369  *  buffer      [O] Destination for volume information
1370  *  length      [I] Size of FsInformation
1371  *  info_class  [I] Type of volume information to set
1372  *
1373  * RETURNS
1374  *  Success: 0. io and buffer are updated.
1375  *  Failure: An NTSTATUS error code describing the error.
1376  */
1377 NTSTATUS WINAPI NtQueryVolumeInformationFile( HANDLE handle, PIO_STATUS_BLOCK io,
1378                                               PVOID buffer, ULONG length,
1379                                               FS_INFORMATION_CLASS info_class )
1380 {
1381     int fd;
1382     struct stat st;
1383
1384     if ((io->u.Status = wine_server_handle_to_fd( handle, 0, &fd, NULL )) != STATUS_SUCCESS)
1385         return io->u.Status;
1386
1387     io->u.Status = STATUS_NOT_IMPLEMENTED;
1388     io->Information = 0;
1389
1390     switch( info_class )
1391     {
1392     case FileFsVolumeInformation:
1393         FIXME( "%p: volume info not supported\n", handle );
1394         break;
1395     case FileFsLabelInformation:
1396         FIXME( "%p: label info not supported\n", handle );
1397         break;
1398     case FileFsSizeInformation:
1399         if (length < sizeof(FILE_FS_SIZE_INFORMATION))
1400             io->u.Status = STATUS_BUFFER_TOO_SMALL;
1401         else
1402         {
1403             FILE_FS_SIZE_INFORMATION *info = buffer;
1404
1405             if (fstat( fd, &st ) < 0)
1406             {
1407                 io->u.Status = FILE_GetNtStatus();
1408                 break;
1409             }
1410             if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
1411             {
1412                 io->u.Status = STATUS_INVALID_DEVICE_REQUEST;
1413             }
1414             else
1415             {
1416                 /* Linux's fstatvfs is buggy */
1417 #if !defined(linux) || !defined(HAVE_FSTATFS)
1418                 struct statvfs stfs;
1419
1420                 if (fstatvfs( fd, &stfs ) < 0)
1421                 {
1422                     io->u.Status = FILE_GetNtStatus();
1423                     break;
1424                 }
1425                 info->BytesPerSector = stfs.f_frsize;
1426 #else
1427                 struct statfs stfs;
1428                 if (fstatfs( fd, &stfs ) < 0)
1429                 {
1430                     io->u.Status = FILE_GetNtStatus();
1431                     break;
1432                 }
1433                 info->BytesPerSector = stfs.f_bsize;
1434 #endif
1435                 info->TotalAllocationUnits.QuadPart = stfs.f_blocks;
1436                 info->AvailableAllocationUnits.QuadPart = stfs.f_bavail;
1437                 info->SectorsPerAllocationUnit = 1;
1438                 io->Information = sizeof(*info);
1439                 io->u.Status = STATUS_SUCCESS;
1440             }
1441         }
1442         break;
1443     case FileFsDeviceInformation:
1444         if (length < sizeof(FILE_FS_DEVICE_INFORMATION))
1445             io->u.Status = STATUS_BUFFER_TOO_SMALL;
1446         else
1447         {
1448             FILE_FS_DEVICE_INFORMATION *info = buffer;
1449
1450             info->Characteristics = 0;
1451             if (fstat( fd, &st ) < 0)
1452             {
1453                 io->u.Status = FILE_GetNtStatus();
1454                 break;
1455             }
1456             if (S_ISCHR( st.st_mode ))
1457             {
1458                 info->DeviceType = FILE_DEVICE_UNKNOWN;
1459 #ifdef linux
1460                 switch(major(st.st_rdev))
1461                 {
1462                 case MEM_MAJOR:
1463                     info->DeviceType = FILE_DEVICE_NULL;
1464                     break;
1465                 case TTY_MAJOR:
1466                     info->DeviceType = FILE_DEVICE_SERIAL_PORT;
1467                     break;
1468                 case LP_MAJOR:
1469                     info->DeviceType = FILE_DEVICE_PARALLEL_PORT;
1470                     break;
1471                 }
1472 #endif
1473             }
1474             else if (S_ISBLK( st.st_mode ))
1475             {
1476                 info->DeviceType = FILE_DEVICE_DISK;
1477             }
1478             else if (S_ISFIFO( st.st_mode ) || S_ISSOCK( st.st_mode ))
1479             {
1480                 info->DeviceType = FILE_DEVICE_NAMED_PIPE;
1481             }
1482             else  /* regular file or directory */
1483             {
1484 #if defined(linux) && defined(HAVE_FSTATFS)
1485                 struct statfs stfs;
1486
1487                 /* check for floppy disk */
1488                 if (major(st.st_dev) == FLOPPY_MAJOR)
1489                     info->Characteristics |= FILE_REMOVABLE_MEDIA;
1490
1491                 if (fstatfs( fd, &stfs ) < 0) stfs.f_type = 0;
1492                 switch (stfs.f_type)
1493                 {
1494                 case 0x9660:      /* iso9660 */
1495                 case 0x15013346:  /* udf */
1496                     info->DeviceType = FILE_DEVICE_CD_ROM_FILE_SYSTEM;
1497                     info->Characteristics |= FILE_REMOVABLE_MEDIA|FILE_READ_ONLY_DEVICE;
1498                     break;
1499                 case 0x6969:  /* nfs */
1500                 case 0x517B:  /* smbfs */
1501                 case 0x564c:  /* ncpfs */
1502                     info->DeviceType = FILE_DEVICE_NETWORK_FILE_SYSTEM;
1503                     info->Characteristics |= FILE_REMOTE_DEVICE;
1504                     break;
1505                 case 0x01021994:  /* tmpfs */
1506                 case 0x28cd3d45:  /* cramfs */
1507                 case 0x1373:      /* devfs */
1508                 case 0x9fa0:      /* procfs */
1509                     info->DeviceType = FILE_DEVICE_VIRTUAL_DISK;
1510                     break;
1511                 default:
1512                     info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
1513                     break;
1514                 }
1515 #elif defined(__FreeBSD__)
1516                 struct statfs stfs;
1517
1518                 /* The proper way to do this in FreeBSD seems to be with the
1519                  * name rather than the type, since their linux-compatible
1520                  * fstatfs call converts the name to one of the Linux types.
1521                  */
1522                 if (fstatfs( fd, &stfs ) < 0)
1523                     info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
1524                 else if (!strncmp("cd9660", stfs.f_fstypename,
1525                  sizeof(stfs.f_fstypename)))
1526                 {
1527                     info->DeviceType = FILE_DEVICE_CD_ROM_FILE_SYSTEM;
1528                     /* Don't assume read-only, let the mount options set it
1529                      * below
1530                      */
1531                     info->Characteristics |= FILE_REMOVABLE_MEDIA;
1532                 }
1533                 else if (!strncmp("nfs", stfs.f_fstypename,
1534                  sizeof(stfs.f_fstypename)))
1535                 {
1536                     info->DeviceType = FILE_DEVICE_NETWORK_FILE_SYSTEM;
1537                     info->Characteristics |= FILE_REMOTE_DEVICE;
1538                 }
1539                 else if (!strncmp("nwfs", stfs.f_fstypename,
1540                  sizeof(stfs.f_fstypename)))
1541                 {
1542                     info->DeviceType = FILE_DEVICE_NETWORK_FILE_SYSTEM;
1543                     info->Characteristics |= FILE_REMOTE_DEVICE;
1544                 }
1545                 else if (!strncmp("procfs", stfs.f_fstypename,
1546                  sizeof(stfs.f_fstypename)))
1547                     info->DeviceType = FILE_DEVICE_VIRTUAL_DISK;
1548                 else
1549                     info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
1550                 if (stfs.f_flags & MNT_RDONLY)
1551                     info->Characteristics |= FILE_READ_ONLY_DEVICE;
1552                 if (!(stfs.f_flags & MNT_LOCAL))
1553                 {
1554                     info->DeviceType = FILE_DEVICE_NETWORK_FILE_SYSTEM;
1555                     info->Characteristics |= FILE_REMOTE_DEVICE;
1556                 }
1557 #elif defined (__APPLE__)
1558                 struct statfs stfs;
1559                 
1560                 info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
1561                 
1562                 if (fstatfs( fd, &stfs ) < 0) break;
1563
1564                 /* stfs.f_type is reserved (always set to 0) so use IOKit */
1565                 kern_return_t kernResult = KERN_FAILURE; 
1566                 mach_port_t masterPort;
1567                 
1568                 char bsdName[6]; /* disk#\0 */
1569                 const char *name = stfs.f_mntfromname + strlen(_PATH_DEV);
1570                 memcpy( bsdName, name, min(strlen(name)+1,sizeof(bsdName)) );
1571                 bsdName[sizeof(bsdName)-1] = 0;
1572
1573                 kernResult = IOMasterPort(MACH_PORT_NULL, &masterPort);
1574
1575                 if (kernResult == KERN_SUCCESS)
1576                 {
1577                     CFMutableDictionaryRef matching = IOBSDNameMatching(masterPort, 0, bsdName);
1578                     
1579                     if (matching)
1580                     {
1581                         CFMutableDictionaryRef properties;
1582                         io_service_t devService = IOServiceGetMatchingService(masterPort, matching);
1583                         
1584                         if (IORegistryEntryCreateCFProperties(devService, 
1585                                                                 &properties,
1586                                                                 kCFAllocatorDefault, 0) != KERN_SUCCESS)
1587                                                                     break;
1588                         if ( CFEqual(
1589                                         CFDictionaryGetValue(properties, CFSTR("Removable")),
1590                                         kCFBooleanTrue)
1591                             ) info->Characteristics |= FILE_REMOVABLE_MEDIA;
1592                             
1593                         if ( CFEqual(
1594                                         CFDictionaryGetValue(properties, CFSTR("Writable")),
1595                                         kCFBooleanFalse)
1596                             ) info->Characteristics |= FILE_READ_ONLY_DEVICE;
1597
1598                         /*
1599                             NB : mounted disk image (.img/.dmg) don't provide specific type
1600                         */
1601                         CFStringRef type;
1602                         if ( (type = CFDictionaryGetValue(properties, CFSTR("Type"))) )
1603                         {
1604                             if ( CFStringCompare(type, CFSTR("CD-ROM"), 0) == kCFCompareEqualTo
1605                                 || CFStringCompare(type, CFSTR("DVD-ROM"), 0) == kCFCompareEqualTo
1606                             )
1607                             {
1608                                 info->DeviceType = FILE_DEVICE_CD_ROM_FILE_SYSTEM;
1609                             }
1610                         } 
1611                         
1612                         if (properties)
1613                             CFRelease(properties);
1614                     }
1615                 }
1616 #elif defined(sun)
1617                 /* Use dkio to work out device types */
1618                 {
1619 # include <sys/dkio.h>
1620 # include <sys/vtoc.h>
1621                     struct dk_cinfo dkinf;
1622                     int retval = ioctl(fd, DKIOCINFO, &dkinf);
1623                     if(retval==-1){
1624                         WARN("Unable to get disk device type information - assuming a disk like device\n");
1625                         info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
1626                     }
1627                     switch (dkinf.dki_ctype)
1628                     {
1629                     case DKC_CDROM:
1630                         info->DeviceType = FILE_DEVICE_CD_ROM_FILE_SYSTEM;
1631                         info->Characteristics |= FILE_REMOVABLE_MEDIA|FILE_READ_ONLY_DEVICE;
1632                         break;
1633                     case DKC_NCRFLOPPY:
1634                     case DKC_SMSFLOPPY:
1635                     case DKC_INTEL82072:
1636                     case DKC_INTEL82077:
1637                         info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
1638                         info->Characteristics |= FILE_REMOVABLE_MEDIA;
1639                         break;
1640                     case DKC_MD:
1641                         info->DeviceType = FILE_DEVICE_VIRTUAL_DISK;
1642                         break;
1643                     default:
1644                         info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
1645                     }
1646                 }
1647 #else
1648                 static int warned;
1649                 if (!warned++) FIXME( "device info not properly supported on this platform\n" );
1650                 info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
1651 #endif
1652                 info->Characteristics |= FILE_DEVICE_IS_MOUNTED;
1653             }
1654             io->Information = sizeof(*info);
1655             io->u.Status = STATUS_SUCCESS;
1656         }
1657         break;
1658     case FileFsAttributeInformation:
1659         FIXME( "%p: attribute info not supported\n", handle );
1660         break;
1661     case FileFsControlInformation:
1662         FIXME( "%p: control info not supported\n", handle );
1663         break;
1664     case FileFsFullSizeInformation:
1665         FIXME( "%p: full size info not supported\n", handle );
1666         break;
1667     case FileFsObjectIdInformation:
1668         FIXME( "%p: object id info not supported\n", handle );
1669         break;
1670     case FileFsMaximumInformation:
1671         FIXME( "%p: maximum info not supported\n", handle );
1672         break;
1673     default:
1674         io->u.Status = STATUS_INVALID_PARAMETER;
1675         break;
1676     }
1677     wine_server_release_fd( handle, fd );
1678     return io->u.Status;
1679 }
1680
1681
1682 /******************************************************************
1683  *              NtFlushBuffersFile  (NTDLL.@)
1684  *
1685  * Flush any buffered data on an open file handle.
1686  *
1687  * PARAMS
1688  *  FileHandle         [I] Handle returned from ZwOpenFile() or ZwCreateFile()
1689  *  IoStatusBlock      [O] Receives information about the operation on return
1690  *
1691  * RETURNS
1692  *  Success: 0. IoStatusBlock is updated.
1693  *  Failure: An NTSTATUS error code describing the error.
1694  */
1695 NTSTATUS WINAPI NtFlushBuffersFile( HANDLE hFile, IO_STATUS_BLOCK* IoStatusBlock )
1696 {
1697     NTSTATUS ret;
1698     HANDLE hEvent = NULL;
1699
1700     SERVER_START_REQ( flush_file )
1701     {
1702         req->handle = hFile;
1703         ret = wine_server_call( req );
1704         hEvent = reply->event;
1705     }
1706     SERVER_END_REQ;
1707     if (!ret && hEvent)
1708     {
1709         ret = NtWaitForSingleObject( hEvent, FALSE, NULL );
1710         NtClose( hEvent );
1711     }
1712     return ret;
1713 }
1714
1715 /******************************************************************
1716  *              NtLockFile       (NTDLL.@)
1717  *
1718  *
1719  */
1720 NTSTATUS WINAPI NtLockFile( HANDLE hFile, HANDLE lock_granted_event,
1721                             PIO_APC_ROUTINE apc, void* apc_user,
1722                             PIO_STATUS_BLOCK io_status, PLARGE_INTEGER offset,
1723                             PLARGE_INTEGER count, ULONG* key, BOOLEAN dont_wait,
1724                             BOOLEAN exclusive )
1725 {
1726     NTSTATUS    ret;
1727     HANDLE      handle;
1728     BOOLEAN     async;
1729
1730     if (apc || io_status || key)
1731     {
1732         FIXME("Unimplemented yet parameter\n");
1733         return STATUS_NOT_IMPLEMENTED;
1734     }
1735
1736     for (;;)
1737     {
1738         SERVER_START_REQ( lock_file )
1739         {
1740             req->handle      = hFile;
1741             req->offset_low  = offset->u.LowPart;
1742             req->offset_high = offset->u.HighPart;
1743             req->count_low   = count->u.LowPart;
1744             req->count_high  = count->u.HighPart;
1745             req->shared      = !exclusive;
1746             req->wait        = !dont_wait;
1747             ret = wine_server_call( req );
1748             handle = reply->handle;
1749             async  = reply->overlapped;
1750         }
1751         SERVER_END_REQ;
1752         if (ret != STATUS_PENDING)
1753         {
1754             if (!ret && lock_granted_event) NtSetEvent(lock_granted_event, NULL);
1755             return ret;
1756         }
1757
1758         if (async)
1759         {
1760             FIXME( "Async I/O lock wait not implemented, might deadlock\n" );
1761             if (handle) NtClose( handle );
1762             return STATUS_PENDING;
1763         }
1764         if (handle)
1765         {
1766             NtWaitForSingleObject( handle, FALSE, NULL );
1767             NtClose( handle );
1768         }
1769         else
1770         {
1771             LARGE_INTEGER time;
1772     
1773             /* Unix lock conflict, sleep a bit and retry */
1774             time.QuadPart = 100 * (ULONGLONG)10000;
1775             time.QuadPart = -time.QuadPart;
1776             NtDelayExecution( FALSE, &time );
1777         }
1778     }
1779 }
1780
1781
1782 /******************************************************************
1783  *              NtUnlockFile    (NTDLL.@)
1784  *
1785  *
1786  */
1787 NTSTATUS WINAPI NtUnlockFile( HANDLE hFile, PIO_STATUS_BLOCK io_status,
1788                               PLARGE_INTEGER offset, PLARGE_INTEGER count,
1789                               PULONG key )
1790 {
1791     NTSTATUS status;
1792
1793     TRACE( "%p %lx%08lx %lx%08lx\n",
1794            hFile, offset->u.HighPart, offset->u.LowPart, count->u.HighPart, count->u.LowPart );
1795
1796     if (io_status || key)
1797     {
1798         FIXME("Unimplemented yet parameter\n");
1799         return STATUS_NOT_IMPLEMENTED;
1800     }
1801
1802     SERVER_START_REQ( unlock_file )
1803     {
1804         req->handle      = hFile;
1805         req->offset_low  = offset->u.LowPart;
1806         req->offset_high = offset->u.HighPart;
1807         req->count_low   = count->u.LowPart;
1808         req->count_high  = count->u.HighPart;
1809         status = wine_server_call( req );
1810     }
1811     SERVER_END_REQ;
1812     return status;
1813 }
1814
1815 /******************************************************************
1816  *              NtCreateNamedPipeFile    (NTDLL.@)
1817  *
1818  *
1819  */
1820 NTSTATUS WINAPI NtCreateNamedPipeFile( PHANDLE handle, ULONG access,
1821                                        POBJECT_ATTRIBUTES oa, PIO_STATUS_BLOCK iosb,
1822                                        ULONG sharing, ULONG dispo, ULONG options,
1823                                        ULONG pipe_type, ULONG read_mode, 
1824                                        ULONG completion_mode, ULONG max_inst,
1825                                        ULONG inbound_quota, ULONG outbound_quota,
1826                                        PLARGE_INTEGER timeout)
1827 {
1828     NTSTATUS    status;
1829     static const WCHAR leadin[] = {'\\','?','?','\\','P','I','P','E','\\'};
1830
1831     TRACE("(%p %lx %p %p %lx %ld %lx %ld %ld %ld %ld %ld %ld %p): stub\n",
1832           handle, access, oa, iosb, sharing, dispo, options, pipe_type,
1833           read_mode, completion_mode, max_inst, inbound_quota, outbound_quota,
1834           timeout);
1835
1836     if (oa->ObjectName->Length < sizeof(leadin) ||
1837         strncmpiW( oa->ObjectName->Buffer, 
1838                    leadin, sizeof(leadin)/sizeof(leadin[0]) ))
1839         return STATUS_OBJECT_NAME_INVALID;
1840     /* assume we only get relative timeout, and storable in a DWORD as ms */
1841     if (timeout->QuadPart > 0 || (timeout->QuadPart / -10000) >> 32)
1842         FIXME("Wrong time %s\n", wine_dbgstr_longlong(timeout->QuadPart));
1843
1844     SERVER_START_REQ( create_named_pipe )
1845     {
1846         req->options = options; /* FIXME not used in server yet !!!! */
1847         req->flags = 
1848             (pipe_type) ? NAMED_PIPE_MESSAGE_STREAM_WRITE : 0 |
1849             (read_mode) ? NAMED_PIPE_MESSAGE_STREAM_READ  : 0 |
1850             (completion_mode) ? NAMED_PIPE_NONBLOCKING_MODE  : 0;
1851         req->maxinstances = max_inst;
1852         req->outsize = outbound_quota;
1853         req->insize  = inbound_quota;
1854         req->timeout = timeout->QuadPart / -10000;
1855         req->inherit = (oa->Attributes & OBJ_INHERIT) != 0;
1856         wine_server_add_data( req, oa->ObjectName->Buffer + 4, 
1857                               oa->ObjectName->Length - 4 * sizeof(WCHAR) );
1858         status = wine_server_call( req );
1859         if (!status) *handle = reply->handle;
1860     }
1861     SERVER_END_REQ;
1862     return status;
1863 }
1864
1865 /******************************************************************
1866  *              NtDeleteFile    (NTDLL.@)
1867  *
1868  *
1869  */
1870 NTSTATUS WINAPI NtDeleteFile( POBJECT_ATTRIBUTES ObjectAttributes )
1871 {
1872     NTSTATUS status;
1873     HANDLE hFile;
1874     IO_STATUS_BLOCK io;
1875
1876     TRACE("%p\n", ObjectAttributes);
1877     status = NtCreateFile( &hFile, GENERIC_READ | GENERIC_WRITE, ObjectAttributes, 
1878                            &io, NULL, 0,
1879                            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 
1880                            FILE_OPEN, FILE_DELETE_ON_CLOSE, NULL, 0 );
1881     if (status == STATUS_SUCCESS) status = NtClose(hFile);
1882     return status;
1883 }
1884
1885 /******************************************************************
1886  *              NtCancelIoFile    (NTDLL.@)
1887  *
1888  *
1889  */
1890 NTSTATUS WINAPI NtCancelIoFile( HANDLE hFile, PIO_STATUS_BLOCK io_status )
1891 {
1892     LARGE_INTEGER timeout;
1893
1894     TRACE("%p %p\n", hFile, io_status );
1895
1896     SERVER_START_REQ( cancel_async )
1897     {
1898         req->handle = hFile;
1899         wine_server_call( req );
1900     }
1901     SERVER_END_REQ;
1902     /* Let some APC be run, so that we can run the remaining APCs on hFile
1903      * either the cancelation of the pending one, but also the execution
1904      * of the queued APC, but not yet run. This is needed to ensure proper
1905      * clean-up of allocated data.
1906      */
1907     timeout.u.LowPart = timeout.u.HighPart = 0;
1908     return io_status->u.Status = NtDelayExecution( TRUE, &timeout );
1909 }
1910
1911 /******************************************************************************
1912  *  NtCreateMailslotFile        [NTDLL.@]
1913  *  ZwCreateMailslotFile        [NTDLL.@]
1914  *
1915  * PARAMS
1916  *  pHandle          [O] pointer to receive the handle created
1917  *  DesiredAccess    [I] access mode (read, write, etc)
1918  *  ObjectAttributes [I] fully qualified NT path of the mailslot
1919  *  IoStatusBlock    [O] receives completion status and other info
1920  *  CreateOptions    [I]
1921  *  MailslotQuota    [I]
1922  *  MaxMessageSize   [I]
1923  *  TimeOut          [I]
1924  *
1925  * RETURNS
1926  *  An NT status code
1927  */
1928 NTSTATUS WINAPI NtCreateMailslotFile(PHANDLE pHandle, ULONG DesiredAccess,
1929      POBJECT_ATTRIBUTES attr, PIO_STATUS_BLOCK IoStatusBlock,
1930      ULONG CreateOptions, ULONG MailslotQuota, ULONG MaxMessageSize,
1931      PLARGE_INTEGER TimeOut)
1932 {
1933     static const WCHAR leadin[] = {
1934         '\\','?','?','\\','M','A','I','L','S','L','O','T','\\'};
1935     NTSTATUS ret;
1936
1937     TRACE("%p %08lx %p %p %08lx %08lx %08lx %p\n",
1938               pHandle, DesiredAccess, attr, IoStatusBlock,
1939               CreateOptions, MailslotQuota, MaxMessageSize, TimeOut);
1940
1941     if (attr->ObjectName->Length < sizeof(leadin) ||
1942         strncmpiW( attr->ObjectName->Buffer, 
1943                    leadin, sizeof(leadin)/sizeof(leadin[0]) ))
1944     {
1945         return STATUS_OBJECT_NAME_INVALID;
1946     }
1947
1948     SERVER_START_REQ( create_mailslot )
1949     {
1950         req->max_msgsize = MaxMessageSize;
1951         req->read_timeout = TimeOut->QuadPart / -10000;
1952         req->inherit = (attr->Attributes & OBJ_INHERIT) != 0;
1953         wine_server_add_data( req, attr->ObjectName->Buffer + 4,
1954                               attr->ObjectName->Length - 4*sizeof(WCHAR) );
1955         ret = wine_server_call( req );
1956         if( ret == STATUS_SUCCESS )
1957             *pHandle = reply->handle;
1958     }
1959     SERVER_END_REQ;
1960  
1961     return ret;
1962 }