2 * Copyright 1999, 2000 Juergen Schmied
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.
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.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "wine/port.h"
30 #ifdef HAVE_SYS_ERRNO_H
31 #include <sys/errno.h>
33 #ifdef HAVE_LINUX_MAJOR_H
34 # include <linux/major.h>
36 #ifdef HAVE_SYS_STATVFS_H
37 # include <sys/statvfs.h>
39 #ifdef HAVE_SYS_PARAM_H
40 # include <sys/param.h>
42 #ifdef HAVE_SYS_TIME_H
43 # include <sys/time.h>
45 #ifdef HAVE_SYS_IOCTL_H
46 #include <sys/ioctl.h>
51 #ifdef HAVE_SYS_POLL_H
54 #ifdef HAVE_SYS_SOCKET_H
55 #include <sys/socket.h>
63 #ifdef HAVE_SYS_MOUNT_H
64 # include <sys/mount.h>
66 #ifdef HAVE_SYS_STATFS_H
67 # include <sys/statfs.h>
70 #define NONAMELESSUNION
71 #define NONAMELESSSTRUCT
73 #define WIN32_NO_STATUS
74 #include "wine/unicode.h"
75 #include "wine/debug.h"
77 #include "wine/server.h"
78 #include "ntdll_misc.h"
82 #include "ddk/ntddser.h"
84 WINE_DEFAULT_DEBUG_CHANNEL(ntdll
);
86 mode_t FILE_umask
= 0;
88 #define SECSPERDAY 86400
89 #define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY)
91 /**************************************************************************
92 * NtOpenFile [NTDLL.@]
93 * ZwOpenFile [NTDLL.@]
98 * handle [O] Variable that receives the file handle on return
99 * access [I] Access desired by the caller to the file
100 * attr [I] Structure describing the file to be opened
101 * io [O] Receives details about the result of the operation
102 * sharing [I] Type of shared access the caller requires
103 * options [I] Options for the file open
106 * Success: 0. FileHandle and IoStatusBlock are updated.
107 * Failure: An NTSTATUS error code describing the error.
109 NTSTATUS WINAPI
NtOpenFile( PHANDLE handle
, ACCESS_MASK access
,
110 POBJECT_ATTRIBUTES attr
, PIO_STATUS_BLOCK io
,
111 ULONG sharing
, ULONG options
)
113 return NtCreateFile( handle
, access
, attr
, io
, NULL
, 0,
114 sharing
, FILE_OPEN
, options
, NULL
, 0 );
117 /**************************************************************************
118 * NtCreateFile [NTDLL.@]
119 * ZwCreateFile [NTDLL.@]
121 * Either create a new file or directory, or open an existing file, device,
122 * directory or volume.
125 * handle [O] Points to a variable which receives the file handle on return
126 * access [I] Desired access to the file
127 * attr [I] Structure describing the file
128 * io [O] Receives information about the operation on return
129 * alloc_size [I] Initial size of the file in bytes
130 * attributes [I] Attributes to create the file with
131 * sharing [I] Type of shared access the caller would like to the file
132 * disposition [I] Specifies what to do, depending on whether the file already exists
133 * options [I] Options for creating a new file
134 * ea_buffer [I] Pointer to an extended attributes buffer
135 * ea_length [I] Length of ea_buffer
138 * Success: 0. handle and io are updated.
139 * Failure: An NTSTATUS error code describing the error.
141 NTSTATUS WINAPI
NtCreateFile( PHANDLE handle
, ACCESS_MASK access
, POBJECT_ATTRIBUTES attr
,
142 PIO_STATUS_BLOCK io
, PLARGE_INTEGER alloc_size
,
143 ULONG attributes
, ULONG sharing
, ULONG disposition
,
144 ULONG options
, PVOID ea_buffer
, ULONG ea_length
)
146 ANSI_STRING unix_name
;
149 TRACE("handle=%p access=%08x name=%s objattr=%08x root=%p sec=%p io=%p alloc_size=%p\n"
150 "attr=%08x sharing=%08x disp=%d options=%08x ea=%p.0x%08x\n",
151 handle
, access
, debugstr_us(attr
->ObjectName
), attr
->Attributes
,
152 attr
->RootDirectory
, attr
->SecurityDescriptor
, io
, alloc_size
,
153 attributes
, sharing
, disposition
, options
, ea_buffer
, ea_length
);
155 if (!attr
|| !attr
->ObjectName
) return STATUS_INVALID_PARAMETER
;
157 if (alloc_size
) FIXME( "alloc_size not supported\n" );
159 if (attr
->RootDirectory
)
161 FIXME( "RootDirectory %p not supported\n", attr
->RootDirectory
);
162 return STATUS_OBJECT_NAME_NOT_FOUND
;
165 io
->u
.Status
= wine_nt_to_unix_file_name( attr
->ObjectName
, &unix_name
, disposition
,
166 !(attr
->Attributes
& OBJ_CASE_INSENSITIVE
) );
168 if (io
->u
.Status
== STATUS_BAD_DEVICE_TYPE
)
170 SERVER_START_REQ( open_file_object
)
172 req
->access
= access
;
173 req
->attributes
= attr
->Attributes
;
174 req
->rootdir
= attr
->RootDirectory
;
175 req
->sharing
= sharing
;
176 req
->options
= options
;
177 wine_server_add_data( req
, attr
->ObjectName
->Buffer
, attr
->ObjectName
->Length
);
178 io
->u
.Status
= wine_server_call( req
);
179 *handle
= reply
->handle
;
185 if (io
->u
.Status
== STATUS_NO_SUCH_FILE
&&
186 disposition
!= FILE_OPEN
&& disposition
!= FILE_OVERWRITE
)
189 io
->u
.Status
= STATUS_SUCCESS
;
192 if (io
->u
.Status
== STATUS_SUCCESS
)
194 SERVER_START_REQ( create_file
)
196 req
->access
= access
;
197 req
->attributes
= attr
->Attributes
;
198 req
->sharing
= sharing
;
199 req
->create
= disposition
;
200 req
->options
= options
;
201 req
->attrs
= attributes
;
202 wine_server_add_data( req
, unix_name
.Buffer
, unix_name
.Length
);
203 io
->u
.Status
= wine_server_call( req
);
204 *handle
= reply
->handle
;
207 RtlFreeAnsiString( &unix_name
);
209 else WARN("%s not found (%x)\n", debugstr_us(attr
->ObjectName
), io
->u
.Status
);
211 if (io
->u
.Status
== STATUS_SUCCESS
)
213 if (created
) io
->Information
= FILE_CREATED
;
214 else switch(disposition
)
217 io
->Information
= FILE_SUPERSEDED
;
220 io
->Information
= FILE_CREATED
;
224 io
->Information
= FILE_OPENED
;
227 case FILE_OVERWRITE_IF
:
228 io
->Information
= FILE_OVERWRITTEN
;
236 /***********************************************************************
237 * Asynchronous file I/O *
249 struct async_fileio io
;
251 unsigned int already
;
258 struct async_fileio io
;
260 unsigned int already
;
262 } async_fileio_write
;
265 /* callback for file I/O user APC */
266 static void WINAPI
fileio_apc( void *arg
, IO_STATUS_BLOCK
*io
, ULONG reserved
)
268 struct async_fileio
*async
= arg
;
269 if (async
->apc
) async
->apc( async
->apc_arg
, io
, reserved
);
270 RtlFreeHeap( GetProcessHeap(), 0, async
);
273 /***********************************************************************
274 * FILE_GetNtStatus(void)
276 * Retrieve the Nt Status code from errno.
277 * Try to be consistent with FILE_SetDosError().
279 NTSTATUS
FILE_GetNtStatus(void)
283 TRACE( "errno = %d\n", errno
);
286 case EAGAIN
: return STATUS_SHARING_VIOLATION
;
287 case EBADF
: return STATUS_INVALID_HANDLE
;
288 case EBUSY
: return STATUS_DEVICE_BUSY
;
289 case ENOSPC
: return STATUS_DISK_FULL
;
292 case EACCES
: return STATUS_ACCESS_DENIED
;
293 case ENOTDIR
: return STATUS_OBJECT_PATH_NOT_FOUND
;
294 case ENOENT
: return STATUS_OBJECT_NAME_NOT_FOUND
;
295 case EISDIR
: return STATUS_FILE_IS_A_DIRECTORY
;
297 case ENFILE
: return STATUS_TOO_MANY_OPENED_FILES
;
298 case EINVAL
: return STATUS_INVALID_PARAMETER
;
299 case ENOTEMPTY
: return STATUS_DIRECTORY_NOT_EMPTY
;
300 case EPIPE
: return STATUS_PIPE_DISCONNECTED
;
301 case EIO
: return STATUS_DEVICE_NOT_READY
;
303 case ENOMEDIUM
: return STATUS_NO_MEDIA_IN_DEVICE
;
305 case ENXIO
: return STATUS_NO_SUCH_DEVICE
;
307 case EOPNOTSUPP
:return STATUS_NOT_SUPPORTED
;
308 case ECONNRESET
:return STATUS_PIPE_DISCONNECTED
;
309 case EFAULT
: return STATUS_ACCESS_VIOLATION
;
310 case ESPIPE
: return STATUS_ILLEGAL_FUNCTION
;
311 case ENOEXEC
: /* ?? */
312 case EEXIST
: /* ?? */
314 FIXME( "Converting errno %d to STATUS_UNSUCCESSFUL\n", err
);
315 return STATUS_UNSUCCESSFUL
;
319 /***********************************************************************
320 * FILE_AsyncReadService (INTERNAL)
322 static NTSTATUS
FILE_AsyncReadService(void *user
, PIO_STATUS_BLOCK iosb
, NTSTATUS status
)
324 async_fileio_read
*fileio
= user
;
325 int fd
, needs_close
, result
;
329 case STATUS_ALERTED
: /* got some new data */
330 /* check to see if the data is ready (non-blocking) */
331 if ((status
= server_get_unix_fd( fileio
->io
.handle
, FILE_READ_DATA
, &fd
,
332 &needs_close
, NULL
, NULL
)))
335 result
= read(fd
, &fileio
->buffer
[fileio
->already
], fileio
->count
- fileio
->already
);
336 if (needs_close
) close( fd
);
340 if (errno
== EAGAIN
|| errno
== EINTR
)
341 status
= STATUS_PENDING
;
342 else /* check to see if the transfer is complete */
343 status
= FILE_GetNtStatus();
345 else if (result
== 0)
347 status
= fileio
->already
? STATUS_SUCCESS
: STATUS_PIPE_BROKEN
;
351 fileio
->already
+= result
;
352 if (fileio
->already
>= fileio
->count
|| fileio
->avail_mode
)
353 status
= STATUS_SUCCESS
;
356 /* if we only have to read the available data, and none is available,
357 * simply cancel the request. If data was available, it has been read
358 * while in by previous call (NtDelayExecution)
360 status
= (fileio
->avail_mode
) ? STATUS_SUCCESS
: STATUS_PENDING
;
366 case STATUS_IO_TIMEOUT
:
367 if (fileio
->already
) status
= STATUS_SUCCESS
;
370 if (status
!= STATUS_PENDING
)
372 iosb
->u
.Status
= status
;
373 iosb
->Information
= fileio
->already
;
380 int interval
; /* max interval between two bytes */
381 int total
; /* total timeout for the whole operation */
382 int end_time
; /* absolute time of end of operation */
385 /* retrieve the I/O timeouts to use for a given handle */
386 static NTSTATUS
get_io_timeouts( HANDLE handle
, enum server_fd_type type
, ULONG count
, BOOL is_read
,
387 struct io_timeouts
*timeouts
)
389 NTSTATUS status
= STATUS_SUCCESS
;
391 timeouts
->interval
= timeouts
->total
= -1;
397 /* GetCommTimeouts */
401 status
= NtDeviceIoControlFile( handle
, NULL
, NULL
, NULL
, &io
,
402 IOCTL_SERIAL_GET_TIMEOUTS
, NULL
, 0, &st
, sizeof(st
) );
407 if (st
.ReadIntervalTimeout
)
408 timeouts
->interval
= st
.ReadIntervalTimeout
;
410 if (st
.ReadTotalTimeoutMultiplier
|| st
.ReadTotalTimeoutConstant
)
412 timeouts
->total
= st
.ReadTotalTimeoutConstant
;
413 if (st
.ReadTotalTimeoutMultiplier
!= MAXDWORD
)
414 timeouts
->total
+= count
* st
.ReadTotalTimeoutMultiplier
;
416 else if (st
.ReadIntervalTimeout
== MAXDWORD
)
417 timeouts
->interval
= 0;
421 if (st
.WriteTotalTimeoutMultiplier
|| st
.WriteTotalTimeoutConstant
)
423 timeouts
->total
= st
.WriteTotalTimeoutConstant
;
424 if (st
.WriteTotalTimeoutMultiplier
!= MAXDWORD
)
425 timeouts
->total
+= count
* st
.WriteTotalTimeoutMultiplier
;
430 case FD_TYPE_MAILSLOT
:
433 timeouts
->interval
= 0; /* return as soon as we got something */
434 SERVER_START_REQ( set_mailslot_info
)
436 req
->handle
= handle
;
438 if (!(status
= wine_server_call( req
)) &&
439 reply
->read_timeout
!= TIMEOUT_INFINITE
)
440 timeouts
->total
= reply
->read_timeout
/ -10000;
448 if (is_read
) timeouts
->interval
= 0; /* return as soon as we got something */
453 if (timeouts
->total
!= -1) timeouts
->end_time
= NtGetTickCount() + timeouts
->total
;
454 return STATUS_SUCCESS
;
458 /* retrieve the timeout for the next wait, in milliseconds */
459 static inline int get_next_io_timeout( const struct io_timeouts
*timeouts
, ULONG already
)
463 if (timeouts
->total
!= -1)
465 ret
= timeouts
->end_time
- NtGetTickCount();
466 if (ret
< 0) ret
= 0;
468 if (already
&& timeouts
->interval
!= -1)
470 if (ret
== -1 || ret
> timeouts
->interval
) ret
= timeouts
->interval
;
476 /* retrieve the avail_mode flag for async reads */
477 static NTSTATUS
get_io_avail_mode( HANDLE handle
, enum server_fd_type type
, BOOL
*avail_mode
)
479 NTSTATUS status
= STATUS_SUCCESS
;
485 /* GetCommTimeouts */
489 status
= NtDeviceIoControlFile( handle
, NULL
, NULL
, NULL
, &io
,
490 IOCTL_SERIAL_GET_TIMEOUTS
, NULL
, 0, &st
, sizeof(st
) );
492 *avail_mode
= (!st
.ReadTotalTimeoutMultiplier
&&
493 !st
.ReadTotalTimeoutConstant
&&
494 st
.ReadIntervalTimeout
== MAXDWORD
);
497 case FD_TYPE_MAILSLOT
:
511 /******************************************************************************
512 * NtReadFile [NTDLL.@]
513 * ZwReadFile [NTDLL.@]
515 * Read from an open file handle.
518 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
519 * Event [I] Event to signal upon completion (or NULL)
520 * ApcRoutine [I] Callback to call upon completion (or NULL)
521 * ApcContext [I] Context for ApcRoutine (or NULL)
522 * IoStatusBlock [O] Receives information about the operation on return
523 * Buffer [O] Destination for the data read
524 * Length [I] Size of Buffer
525 * ByteOffset [O] Destination for the new file pointer position (or NULL)
526 * Key [O] Function unknown (may be NULL)
529 * Success: 0. IoStatusBlock is updated, and the Information member contains
530 * The number of bytes read.
531 * Failure: An NTSTATUS error code describing the error.
533 NTSTATUS WINAPI
NtReadFile(HANDLE hFile
, HANDLE hEvent
,
534 PIO_APC_ROUTINE apc
, void* apc_user
,
535 PIO_STATUS_BLOCK io_status
, void* buffer
, ULONG length
,
536 PLARGE_INTEGER offset
, PULONG key
)
538 int result
, unix_handle
, needs_close
, timeout_init_done
= 0;
539 unsigned int options
;
540 struct io_timeouts timeouts
;
543 enum server_fd_type type
;
545 TRACE("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%p),partial stub!\n",
546 hFile
,hEvent
,apc
,apc_user
,io_status
,buffer
,length
,offset
,key
);
548 if (!io_status
) return STATUS_ACCESS_VIOLATION
;
550 status
= server_get_unix_fd( hFile
, FILE_READ_DATA
, &unix_handle
,
551 &needs_close
, &type
, &options
);
552 if (status
) return status
;
554 if (type
== FD_TYPE_FILE
&& offset
&& offset
->QuadPart
!= (LONGLONG
)-2 /* FILE_USE_FILE_POINTER_POSITION */ )
556 /* async I/O doesn't make sense on regular files */
557 while ((result
= pread( unix_handle
, buffer
, length
, offset
->QuadPart
)) == -1)
561 status
= FILE_GetNtStatus();
565 if (options
& (FILE_SYNCHRONOUS_IO_ALERT
| FILE_SYNCHRONOUS_IO_NONALERT
))
566 /* update file pointer position */
567 lseek( unix_handle
, offset
->QuadPart
+ result
, SEEK_SET
);
570 status
= total
? STATUS_SUCCESS
: STATUS_END_OF_FILE
;
576 if ((result
= read( unix_handle
, (char *)buffer
+ total
, length
- total
)) >= 0)
579 if (!result
|| total
== length
)
582 status
= STATUS_SUCCESS
;
584 status
= (type
== FD_TYPE_FILE
|| type
== FD_TYPE_CHAR
) ? STATUS_END_OF_FILE
: STATUS_PIPE_BROKEN
;
590 if (errno
== EINTR
) continue;
593 status
= FILE_GetNtStatus();
598 if (!(options
& (FILE_SYNCHRONOUS_IO_ALERT
| FILE_SYNCHRONOUS_IO_NONALERT
)))
600 async_fileio_read
*fileio
;
603 if ((status
= get_io_avail_mode( hFile
, type
, &avail_mode
)))
605 if (total
&& avail_mode
)
607 status
= STATUS_SUCCESS
;
611 if (!(fileio
= RtlAllocateHeap(GetProcessHeap(), 0, sizeof(*fileio
))))
613 status
= STATUS_NO_MEMORY
;
616 fileio
->io
.handle
= hFile
;
617 fileio
->io
.apc
= apc
;
618 fileio
->io
.apc_arg
= apc_user
;
619 fileio
->already
= total
;
620 fileio
->count
= length
;
621 fileio
->buffer
= buffer
;
622 fileio
->avail_mode
= avail_mode
;
624 SERVER_START_REQ( register_async
)
627 req
->type
= ASYNC_TYPE_READ
;
629 req
->async
.callback
= FILE_AsyncReadService
;
630 req
->async
.iosb
= io_status
;
631 req
->async
.arg
= fileio
;
632 req
->async
.apc
= fileio_apc
;
633 req
->async
.event
= hEvent
;
634 status
= wine_server_call( req
);
638 if (status
!= STATUS_PENDING
) RtlFreeHeap( GetProcessHeap(), 0, fileio
);
641 else /* synchronous read, wait for the fd to become ready */
646 if (!timeout_init_done
)
648 timeout_init_done
= 1;
649 if ((status
= get_io_timeouts( hFile
, type
, length
, TRUE
, &timeouts
)))
651 if (hEvent
) NtResetEvent( hEvent
, NULL
);
653 timeout
= get_next_io_timeout( &timeouts
, total
);
655 pfd
.fd
= unix_handle
;
658 if (!timeout
|| !(ret
= poll( &pfd
, 1, timeout
)))
660 if (total
) /* return with what we got so far */
661 status
= STATUS_SUCCESS
;
663 status
= (type
== FD_TYPE_MAILSLOT
) ? STATUS_IO_TIMEOUT
: STATUS_TIMEOUT
;
666 if (ret
== -1 && errno
!= EINTR
)
668 status
= FILE_GetNtStatus();
671 /* will now restart the read */
676 if (needs_close
) close( unix_handle
);
677 if (status
== STATUS_SUCCESS
)
679 io_status
->u
.Status
= status
;
680 io_status
->Information
= total
;
681 TRACE("= SUCCESS (%u)\n", total
);
682 if (hEvent
) NtSetEvent( hEvent
, NULL
);
683 if (apc
) NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC
)apc
,
684 (ULONG_PTR
)apc_user
, (ULONG_PTR
)io_status
, 0 );
688 TRACE("= 0x%08x\n", status
);
689 if (status
!= STATUS_PENDING
&& hEvent
) NtResetEvent( hEvent
, NULL
);
694 /***********************************************************************
695 * FILE_AsyncWriteService (INTERNAL)
697 static NTSTATUS
FILE_AsyncWriteService(void *user
, IO_STATUS_BLOCK
*iosb
, NTSTATUS status
)
699 async_fileio_write
*fileio
= user
;
700 int result
, fd
, needs_close
;
701 enum server_fd_type type
;
706 /* write some data (non-blocking) */
707 if ((status
= server_get_unix_fd( fileio
->io
.handle
, FILE_WRITE_DATA
, &fd
,
708 &needs_close
, &type
, NULL
)))
711 if (!fileio
->count
&& (type
== FD_TYPE_MAILSLOT
|| type
== FD_TYPE_PIPE
|| type
== FD_TYPE_SOCKET
))
712 result
= send( fd
, fileio
->buffer
, 0, 0 );
714 result
= write( fd
, &fileio
->buffer
[fileio
->already
], fileio
->count
- fileio
->already
);
716 if (needs_close
) close( fd
);
720 if (errno
== EAGAIN
|| errno
== EINTR
) status
= STATUS_PENDING
;
721 else status
= FILE_GetNtStatus();
725 fileio
->already
+= result
;
726 status
= (fileio
->already
< fileio
->count
) ? STATUS_PENDING
: STATUS_SUCCESS
;
731 case STATUS_IO_TIMEOUT
:
732 if (fileio
->already
) status
= STATUS_SUCCESS
;
735 if (status
!= STATUS_PENDING
)
737 iosb
->u
.Status
= status
;
738 iosb
->Information
= fileio
->already
;
743 /******************************************************************************
744 * NtWriteFile [NTDLL.@]
745 * ZwWriteFile [NTDLL.@]
747 * Write to an open file handle.
750 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
751 * Event [I] Event to signal upon completion (or NULL)
752 * ApcRoutine [I] Callback to call upon completion (or NULL)
753 * ApcContext [I] Context for ApcRoutine (or NULL)
754 * IoStatusBlock [O] Receives information about the operation on return
755 * Buffer [I] Source for the data to write
756 * Length [I] Size of Buffer
757 * ByteOffset [O] Destination for the new file pointer position (or NULL)
758 * Key [O] Function unknown (may be NULL)
761 * Success: 0. IoStatusBlock is updated, and the Information member contains
762 * The number of bytes written.
763 * Failure: An NTSTATUS error code describing the error.
765 NTSTATUS WINAPI
NtWriteFile(HANDLE hFile
, HANDLE hEvent
,
766 PIO_APC_ROUTINE apc
, void* apc_user
,
767 PIO_STATUS_BLOCK io_status
,
768 const void* buffer
, ULONG length
,
769 PLARGE_INTEGER offset
, PULONG key
)
771 int result
, unix_handle
, needs_close
, timeout_init_done
= 0;
772 unsigned int options
;
773 struct io_timeouts timeouts
;
776 enum server_fd_type type
;
778 TRACE("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%p)!\n",
779 hFile
,hEvent
,apc
,apc_user
,io_status
,buffer
,length
,offset
,key
);
781 if (!io_status
) return STATUS_ACCESS_VIOLATION
;
783 status
= server_get_unix_fd( hFile
, FILE_WRITE_DATA
, &unix_handle
,
784 &needs_close
, &type
, &options
);
785 if (status
) return status
;
787 if (type
== FD_TYPE_FILE
&& offset
&& offset
->QuadPart
!= (LONGLONG
)-2 /* FILE_USE_FILE_POINTER_POSITION */ )
789 /* async I/O doesn't make sense on regular files */
790 while ((result
= pwrite( unix_handle
, buffer
, length
, offset
->QuadPart
)) == -1)
794 if (errno
== EFAULT
) status
= STATUS_INVALID_USER_BUFFER
;
795 else status
= FILE_GetNtStatus();
800 if (options
& (FILE_SYNCHRONOUS_IO_ALERT
| FILE_SYNCHRONOUS_IO_NONALERT
))
801 /* update file pointer position */
802 lseek( unix_handle
, offset
->QuadPart
+ result
, SEEK_SET
);
805 status
= STATUS_SUCCESS
;
811 /* zero-length writes on sockets may not work with plain write(2) */
812 if (!length
&& (type
== FD_TYPE_MAILSLOT
|| type
== FD_TYPE_PIPE
|| type
== FD_TYPE_SOCKET
))
813 result
= send( unix_handle
, buffer
, 0, 0 );
815 result
= write( unix_handle
, (const char *)buffer
+ total
, length
- total
);
822 status
= STATUS_SUCCESS
;
828 if (errno
== EINTR
) continue;
831 if (errno
== EFAULT
) status
= STATUS_INVALID_USER_BUFFER
;
832 else status
= FILE_GetNtStatus();
837 if (!(options
& (FILE_SYNCHRONOUS_IO_ALERT
| FILE_SYNCHRONOUS_IO_NONALERT
)))
839 async_fileio_write
*fileio
;
841 if (!(fileio
= RtlAllocateHeap(GetProcessHeap(), 0, sizeof(*fileio
))))
843 status
= STATUS_NO_MEMORY
;
846 fileio
->io
.handle
= hFile
;
847 fileio
->io
.apc
= apc
;
848 fileio
->io
.apc_arg
= apc_user
;
849 fileio
->already
= total
;
850 fileio
->count
= length
;
851 fileio
->buffer
= buffer
;
853 SERVER_START_REQ( register_async
)
856 req
->type
= ASYNC_TYPE_WRITE
;
858 req
->async
.callback
= FILE_AsyncWriteService
;
859 req
->async
.iosb
= io_status
;
860 req
->async
.arg
= fileio
;
861 req
->async
.apc
= fileio_apc
;
862 req
->async
.event
= hEvent
;
863 status
= wine_server_call( req
);
867 if (status
!= STATUS_PENDING
) RtlFreeHeap( GetProcessHeap(), 0, fileio
);
870 else /* synchronous write, wait for the fd to become ready */
875 if (!timeout_init_done
)
877 timeout_init_done
= 1;
878 if ((status
= get_io_timeouts( hFile
, type
, length
, FALSE
, &timeouts
)))
880 if (hEvent
) NtResetEvent( hEvent
, NULL
);
882 timeout
= get_next_io_timeout( &timeouts
, total
);
884 pfd
.fd
= unix_handle
;
885 pfd
.events
= POLLOUT
;
887 if (!timeout
|| !(ret
= poll( &pfd
, 1, timeout
)))
889 /* return with what we got so far */
890 status
= total
? STATUS_SUCCESS
: STATUS_TIMEOUT
;
893 if (ret
== -1 && errno
!= EINTR
)
895 status
= FILE_GetNtStatus();
898 /* will now restart the write */
903 if (needs_close
) close( unix_handle
);
904 if (status
== STATUS_SUCCESS
)
906 io_status
->u
.Status
= status
;
907 io_status
->Information
= total
;
908 TRACE("= SUCCESS (%u)\n", total
);
909 if (hEvent
) NtSetEvent( hEvent
, NULL
);
910 if (apc
) NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC
)apc
,
911 (ULONG_PTR
)apc_user
, (ULONG_PTR
)io_status
, 0 );
915 TRACE("= 0x%08x\n", status
);
916 if (status
!= STATUS_PENDING
&& hEvent
) NtResetEvent( hEvent
, NULL
);
924 HANDLE handle
; /* handle to the device */
925 void *buffer
; /* buffer for output */
926 ULONG size
; /* size of buffer */
927 PIO_APC_ROUTINE apc
; /* user apc params */
931 /* callback for ioctl async I/O completion */
932 static NTSTATUS
ioctl_completion( void *arg
, IO_STATUS_BLOCK
*io
, NTSTATUS status
)
934 struct async_ioctl
*async
= arg
;
936 if (status
== STATUS_ALERTED
)
938 SERVER_START_REQ( get_ioctl_result
)
940 req
->handle
= async
->handle
;
941 req
->user_arg
= async
;
942 wine_server_set_reply( req
, async
->buffer
, async
->size
);
943 if (!(status
= wine_server_call( req
)))
944 io
->Information
= wine_server_reply_size( reply
);
948 if (status
!= STATUS_PENDING
) io
->u
.Status
= status
;
952 /* callback for ioctl user APC */
953 static void WINAPI
ioctl_apc( void *arg
, IO_STATUS_BLOCK
*io
, ULONG reserved
)
955 struct async_ioctl
*async
= arg
;
956 if (async
->apc
) async
->apc( async
->apc_arg
, io
, reserved
);
957 RtlFreeHeap( GetProcessHeap(), 0, async
);
960 /* do a ioctl call through the server */
961 static NTSTATUS
server_ioctl_file( HANDLE handle
, HANDLE event
,
962 PIO_APC_ROUTINE apc
, PVOID apc_context
,
963 IO_STATUS_BLOCK
*io
, ULONG code
,
964 const void *in_buffer
, ULONG in_size
,
965 PVOID out_buffer
, ULONG out_size
)
967 struct async_ioctl
*async
;
972 if (!(async
= RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*async
) )))
973 return STATUS_NO_MEMORY
;
974 async
->handle
= handle
;
975 async
->buffer
= out_buffer
;
976 async
->size
= out_size
;
978 async
->apc_arg
= apc_context
;
980 SERVER_START_REQ( ioctl
)
982 req
->handle
= handle
;
984 req
->async
.callback
= ioctl_completion
;
985 req
->async
.iosb
= io
;
986 req
->async
.arg
= async
;
987 req
->async
.apc
= (apc
|| event
) ? ioctl_apc
: NULL
;
988 req
->async
.event
= event
;
989 wine_server_add_data( req
, in_buffer
, in_size
);
990 wine_server_set_reply( req
, out_buffer
, out_size
);
991 if (!(status
= wine_server_call( req
)))
992 io
->Information
= wine_server_reply_size( reply
);
993 wait_handle
= reply
->wait
;
994 options
= reply
->options
;
998 if (status
== STATUS_NOT_SUPPORTED
)
999 FIXME("Unsupported ioctl %x (device=%x access=%x func=%x method=%x)\n",
1000 code
, code
>> 16, (code
>> 14) & 3, (code
>> 2) & 0xfff, code
& 3);
1002 if (status
!= STATUS_PENDING
) RtlFreeHeap( GetProcessHeap(), 0, async
);
1006 NtWaitForSingleObject( wait_handle
, (options
& FILE_SYNCHRONOUS_IO_ALERT
), NULL
);
1007 status
= io
->u
.Status
;
1008 NtClose( wait_handle
);
1009 RtlFreeHeap( GetProcessHeap(), 0, async
);
1016 /**************************************************************************
1017 * NtDeviceIoControlFile [NTDLL.@]
1018 * ZwDeviceIoControlFile [NTDLL.@]
1020 * Perform an I/O control operation on an open file handle.
1023 * handle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
1024 * event [I] Event to signal upon completion (or NULL)
1025 * apc [I] Callback to call upon completion (or NULL)
1026 * apc_context [I] Context for ApcRoutine (or NULL)
1027 * io [O] Receives information about the operation on return
1028 * code [I] Control code for the operation to perform
1029 * in_buffer [I] Source for any input data required (or NULL)
1030 * in_size [I] Size of InputBuffer
1031 * out_buffer [O] Source for any output data returned (or NULL)
1032 * out_size [I] Size of OutputBuffer
1035 * Success: 0. IoStatusBlock is updated.
1036 * Failure: An NTSTATUS error code describing the error.
1038 NTSTATUS WINAPI
NtDeviceIoControlFile(HANDLE handle
, HANDLE event
,
1039 PIO_APC_ROUTINE apc
, PVOID apc_context
,
1040 PIO_STATUS_BLOCK io
, ULONG code
,
1041 PVOID in_buffer
, ULONG in_size
,
1042 PVOID out_buffer
, ULONG out_size
)
1044 ULONG device
= (code
>> 16);
1047 TRACE("(%p,%p,%p,%p,%p,0x%08x,%p,0x%08x,%p,0x%08x)\n",
1048 handle
, event
, apc
, apc_context
, io
, code
,
1049 in_buffer
, in_size
, out_buffer
, out_size
);
1053 case FILE_DEVICE_DISK
:
1054 case FILE_DEVICE_CD_ROM
:
1055 case FILE_DEVICE_DVD
:
1056 case FILE_DEVICE_CONTROLLER
:
1057 case FILE_DEVICE_MASS_STORAGE
:
1058 status
= CDROM_DeviceIoControl(handle
, event
, apc
, apc_context
, io
, code
,
1059 in_buffer
, in_size
, out_buffer
, out_size
);
1061 case FILE_DEVICE_SERIAL_PORT
:
1062 status
= COMM_DeviceIoControl(handle
, event
, apc
, apc_context
, io
, code
,
1063 in_buffer
, in_size
, out_buffer
, out_size
);
1065 case FILE_DEVICE_TAPE
:
1066 status
= TAPE_DeviceIoControl(handle
, event
, apc
, apc_context
, io
, code
,
1067 in_buffer
, in_size
, out_buffer
, out_size
);
1070 status
= server_ioctl_file( handle
, event
, apc
, apc_context
, io
, code
,
1071 in_buffer
, in_size
, out_buffer
, out_size
);
1074 if (status
!= STATUS_PENDING
) io
->u
.Status
= status
;
1079 /**************************************************************************
1080 * NtFsControlFile [NTDLL.@]
1081 * ZwFsControlFile [NTDLL.@]
1083 * Perform a file system control operation on an open file handle.
1086 * handle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
1087 * event [I] Event to signal upon completion (or NULL)
1088 * apc [I] Callback to call upon completion (or NULL)
1089 * apc_context [I] Context for ApcRoutine (or NULL)
1090 * io [O] Receives information about the operation on return
1091 * code [I] Control code for the operation to perform
1092 * in_buffer [I] Source for any input data required (or NULL)
1093 * in_size [I] Size of InputBuffer
1094 * out_buffer [O] Source for any output data returned (or NULL)
1095 * out_size [I] Size of OutputBuffer
1098 * Success: 0. IoStatusBlock is updated.
1099 * Failure: An NTSTATUS error code describing the error.
1101 NTSTATUS WINAPI
NtFsControlFile(HANDLE handle
, HANDLE event
, PIO_APC_ROUTINE apc
,
1102 PVOID apc_context
, PIO_STATUS_BLOCK io
, ULONG code
,
1103 PVOID in_buffer
, ULONG in_size
, PVOID out_buffer
, ULONG out_size
)
1107 TRACE("(%p,%p,%p,%p,%p,0x%08x,%p,0x%08x,%p,0x%08x)\n",
1108 handle
, event
, apc
, apc_context
, io
, code
,
1109 in_buffer
, in_size
, out_buffer
, out_size
);
1111 if (!io
) return STATUS_INVALID_PARAMETER
;
1115 case FSCTL_DISMOUNT_VOLUME
:
1116 status
= server_ioctl_file( handle
, event
, apc
, apc_context
, io
, code
,
1117 in_buffer
, in_size
, out_buffer
, out_size
);
1118 if (!status
) status
= DIR_unmount_device( handle
);
1121 case FSCTL_PIPE_PEEK
:
1123 FILE_PIPE_PEEK_BUFFER
*buffer
= out_buffer
;
1124 int avail
= 0, fd
, needs_close
;
1126 if (out_size
< FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER
, Data
))
1128 status
= STATUS_INFO_LENGTH_MISMATCH
;
1132 if ((status
= server_get_unix_fd( handle
, FILE_READ_DATA
, &fd
, &needs_close
, NULL
, NULL
)))
1136 if (ioctl( fd
, FIONREAD
, &avail
) != 0)
1138 TRACE("FIONREAD failed reason: %s\n",strerror(errno
));
1139 if (needs_close
) close( fd
);
1140 status
= FILE_GetNtStatus();
1144 if (!avail
) /* check for closed pipe */
1146 struct pollfd pollfd
;
1150 pollfd
.events
= POLLIN
;
1152 ret
= poll( &pollfd
, 1, 0 );
1153 if (ret
== -1 || (ret
== 1 && (pollfd
.revents
& (POLLHUP
|POLLERR
))))
1155 if (needs_close
) close( fd
);
1156 status
= STATUS_PIPE_BROKEN
;
1160 buffer
->NamedPipeState
= 0; /* FIXME */
1161 buffer
->ReadDataAvailable
= avail
;
1162 buffer
->NumberOfMessages
= 0; /* FIXME */
1163 buffer
->MessageLength
= 0; /* FIXME */
1164 io
->Information
= FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER
, Data
);
1165 status
= STATUS_SUCCESS
;
1168 ULONG data_size
= out_size
- FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER
, Data
);
1171 int res
= recv( fd
, buffer
->Data
, data_size
, MSG_PEEK
);
1172 if (res
>= 0) io
->Information
+= res
;
1175 if (needs_close
) close( fd
);
1179 case FSCTL_PIPE_DISCONNECT
:
1180 status
= server_ioctl_file( handle
, event
, apc
, apc_context
, io
, code
,
1181 in_buffer
, in_size
, out_buffer
, out_size
);
1184 int fd
= server_remove_fd_from_cache( handle
);
1185 if (fd
!= -1) close( fd
);
1189 case FSCTL_LOCK_VOLUME
:
1190 case FSCTL_UNLOCK_VOLUME
:
1191 FIXME("stub! return success - Unsupported fsctl %x (device=%x access=%x func=%x method=%x)\n",
1192 code
, code
>> 16, (code
>> 14) & 3, (code
>> 2) & 0xfff, code
& 3);
1193 status
= STATUS_SUCCESS
;
1196 case FSCTL_PIPE_LISTEN
:
1197 case FSCTL_PIPE_WAIT
:
1199 status
= server_ioctl_file( handle
, event
, apc
, apc_context
, io
, code
,
1200 in_buffer
, in_size
, out_buffer
, out_size
);
1204 if (status
!= STATUS_PENDING
) io
->u
.Status
= status
;
1208 /******************************************************************************
1209 * NtSetVolumeInformationFile [NTDLL.@]
1210 * ZwSetVolumeInformationFile [NTDLL.@]
1212 * Set volume information for an open file handle.
1215 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
1216 * IoStatusBlock [O] Receives information about the operation on return
1217 * FsInformation [I] Source for volume information
1218 * Length [I] Size of FsInformation
1219 * FsInformationClass [I] Type of volume information to set
1222 * Success: 0. IoStatusBlock is updated.
1223 * Failure: An NTSTATUS error code describing the error.
1225 NTSTATUS WINAPI
NtSetVolumeInformationFile(
1226 IN HANDLE FileHandle
,
1227 PIO_STATUS_BLOCK IoStatusBlock
,
1228 PVOID FsInformation
,
1230 FS_INFORMATION_CLASS FsInformationClass
)
1232 FIXME("(%p,%p,%p,0x%08x,0x%08x) stub\n",
1233 FileHandle
,IoStatusBlock
,FsInformation
,Length
,FsInformationClass
);
1237 /******************************************************************************
1238 * NtQueryInformationFile [NTDLL.@]
1239 * ZwQueryInformationFile [NTDLL.@]
1241 * Get information about an open file handle.
1244 * hFile [I] Handle returned from ZwOpenFile() or ZwCreateFile()
1245 * io [O] Receives information about the operation on return
1246 * ptr [O] Destination for file information
1247 * len [I] Size of FileInformation
1248 * class [I] Type of file information to get
1251 * Success: 0. IoStatusBlock and FileInformation are updated.
1252 * Failure: An NTSTATUS error code describing the error.
1254 NTSTATUS WINAPI
NtQueryInformationFile( HANDLE hFile
, PIO_STATUS_BLOCK io
,
1255 PVOID ptr
, LONG len
, FILE_INFORMATION_CLASS
class )
1257 static const size_t info_sizes
[] =
1260 sizeof(FILE_DIRECTORY_INFORMATION
), /* FileDirectoryInformation */
1261 sizeof(FILE_FULL_DIRECTORY_INFORMATION
), /* FileFullDirectoryInformation */
1262 sizeof(FILE_BOTH_DIRECTORY_INFORMATION
), /* FileBothDirectoryInformation */
1263 sizeof(FILE_BASIC_INFORMATION
), /* FileBasicInformation */
1264 sizeof(FILE_STANDARD_INFORMATION
), /* FileStandardInformation */
1265 sizeof(FILE_INTERNAL_INFORMATION
), /* FileInternalInformation */
1266 sizeof(FILE_EA_INFORMATION
), /* FileEaInformation */
1267 sizeof(FILE_ACCESS_INFORMATION
), /* FileAccessInformation */
1268 sizeof(FILE_NAME_INFORMATION
)-sizeof(WCHAR
), /* FileNameInformation */
1269 sizeof(FILE_RENAME_INFORMATION
)-sizeof(WCHAR
), /* FileRenameInformation */
1270 0, /* FileLinkInformation */
1271 sizeof(FILE_NAMES_INFORMATION
)-sizeof(WCHAR
), /* FileNamesInformation */
1272 sizeof(FILE_DISPOSITION_INFORMATION
), /* FileDispositionInformation */
1273 sizeof(FILE_POSITION_INFORMATION
), /* FilePositionInformation */
1274 sizeof(FILE_FULL_EA_INFORMATION
), /* FileFullEaInformation */
1275 sizeof(FILE_MODE_INFORMATION
), /* FileModeInformation */
1276 sizeof(FILE_ALIGNMENT_INFORMATION
), /* FileAlignmentInformation */
1277 sizeof(FILE_ALL_INFORMATION
)-sizeof(WCHAR
), /* FileAllInformation */
1278 sizeof(FILE_ALLOCATION_INFORMATION
), /* FileAllocationInformation */
1279 sizeof(FILE_END_OF_FILE_INFORMATION
), /* FileEndOfFileInformation */
1280 0, /* FileAlternateNameInformation */
1281 sizeof(FILE_STREAM_INFORMATION
)-sizeof(WCHAR
), /* FileStreamInformation */
1282 0, /* FilePipeInformation */
1283 sizeof(FILE_PIPE_LOCAL_INFORMATION
), /* FilePipeLocalInformation */
1284 0, /* FilePipeRemoteInformation */
1285 sizeof(FILE_MAILSLOT_QUERY_INFORMATION
), /* FileMailslotQueryInformation */
1286 0, /* FileMailslotSetInformation */
1287 0, /* FileCompressionInformation */
1288 0, /* FileObjectIdInformation */
1289 0, /* FileCompletionInformation */
1290 0, /* FileMoveClusterInformation */
1291 0, /* FileQuotaInformation */
1292 0, /* FileReparsePointInformation */
1293 0, /* FileNetworkOpenInformation */
1294 0, /* FileAttributeTagInformation */
1295 0 /* FileTrackingInformation */
1299 int fd
, needs_close
= FALSE
;
1301 TRACE("(%p,%p,%p,0x%08x,0x%08x)\n", hFile
, io
, ptr
, len
, class);
1303 io
->Information
= 0;
1305 if (class <= 0 || class >= FileMaximumInformation
)
1306 return io
->u
.Status
= STATUS_INVALID_INFO_CLASS
;
1307 if (!info_sizes
[class])
1309 FIXME("Unsupported class (%d)\n", class);
1310 return io
->u
.Status
= STATUS_NOT_IMPLEMENTED
;
1312 if (len
< info_sizes
[class])
1313 return io
->u
.Status
= STATUS_INFO_LENGTH_MISMATCH
;
1315 if (class != FilePipeLocalInformation
)
1317 if ((io
->u
.Status
= server_get_unix_fd( hFile
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1318 return io
->u
.Status
;
1323 case FileBasicInformation
:
1325 FILE_BASIC_INFORMATION
*info
= ptr
;
1327 if (fstat( fd
, &st
) == -1)
1328 io
->u
.Status
= FILE_GetNtStatus();
1329 else if (!S_ISREG(st
.st_mode
) && !S_ISDIR(st
.st_mode
))
1330 io
->u
.Status
= STATUS_INVALID_INFO_CLASS
;
1333 if (S_ISDIR(st
.st_mode
)) info
->FileAttributes
= FILE_ATTRIBUTE_DIRECTORY
;
1334 else info
->FileAttributes
= FILE_ATTRIBUTE_ARCHIVE
;
1335 if (!(st
.st_mode
& (S_IWUSR
| S_IWGRP
| S_IWOTH
)))
1336 info
->FileAttributes
|= FILE_ATTRIBUTE_READONLY
;
1337 RtlSecondsSince1970ToTime( st
.st_mtime
, &info
->CreationTime
);
1338 RtlSecondsSince1970ToTime( st
.st_mtime
, &info
->LastWriteTime
);
1339 RtlSecondsSince1970ToTime( st
.st_ctime
, &info
->ChangeTime
);
1340 RtlSecondsSince1970ToTime( st
.st_atime
, &info
->LastAccessTime
);
1344 case FileStandardInformation
:
1346 FILE_STANDARD_INFORMATION
*info
= ptr
;
1348 if (fstat( fd
, &st
) == -1) io
->u
.Status
= FILE_GetNtStatus();
1351 if ((info
->Directory
= S_ISDIR(st
.st_mode
)))
1353 info
->AllocationSize
.QuadPart
= 0;
1354 info
->EndOfFile
.QuadPart
= 0;
1355 info
->NumberOfLinks
= 1;
1356 info
->DeletePending
= FALSE
;
1360 info
->AllocationSize
.QuadPart
= (ULONGLONG
)st
.st_blocks
* 512;
1361 info
->EndOfFile
.QuadPart
= st
.st_size
;
1362 info
->NumberOfLinks
= st
.st_nlink
;
1363 info
->DeletePending
= FALSE
; /* FIXME */
1368 case FilePositionInformation
:
1370 FILE_POSITION_INFORMATION
*info
= ptr
;
1371 off_t res
= lseek( fd
, 0, SEEK_CUR
);
1372 if (res
== (off_t
)-1) io
->u
.Status
= FILE_GetNtStatus();
1373 else info
->CurrentByteOffset
.QuadPart
= res
;
1376 case FileInternalInformation
:
1378 FILE_INTERNAL_INFORMATION
*info
= ptr
;
1380 if (fstat( fd
, &st
) == -1) io
->u
.Status
= FILE_GetNtStatus();
1381 else info
->IndexNumber
.QuadPart
= st
.st_ino
;
1384 case FileEaInformation
:
1386 FILE_EA_INFORMATION
*info
= ptr
;
1390 case FileEndOfFileInformation
:
1392 FILE_END_OF_FILE_INFORMATION
*info
= ptr
;
1394 if (fstat( fd
, &st
) == -1) io
->u
.Status
= FILE_GetNtStatus();
1395 else info
->EndOfFile
.QuadPart
= S_ISDIR(st
.st_mode
) ? 0 : st
.st_size
;
1398 case FileAllInformation
:
1400 FILE_ALL_INFORMATION
*info
= ptr
;
1402 if (fstat( fd
, &st
) == -1) io
->u
.Status
= FILE_GetNtStatus();
1403 else if (!S_ISREG(st
.st_mode
) && !S_ISDIR(st
.st_mode
))
1404 io
->u
.Status
= STATUS_INVALID_INFO_CLASS
;
1407 if ((info
->StandardInformation
.Directory
= S_ISDIR(st
.st_mode
)))
1409 info
->BasicInformation
.FileAttributes
= FILE_ATTRIBUTE_DIRECTORY
;
1410 info
->StandardInformation
.AllocationSize
.QuadPart
= 0;
1411 info
->StandardInformation
.EndOfFile
.QuadPart
= 0;
1412 info
->StandardInformation
.NumberOfLinks
= 1;
1413 info
->StandardInformation
.DeletePending
= FALSE
;
1417 info
->BasicInformation
.FileAttributes
= FILE_ATTRIBUTE_ARCHIVE
;
1418 info
->StandardInformation
.AllocationSize
.QuadPart
= (ULONGLONG
)st
.st_blocks
* 512;
1419 info
->StandardInformation
.EndOfFile
.QuadPart
= st
.st_size
;
1420 info
->StandardInformation
.NumberOfLinks
= st
.st_nlink
;
1421 info
->StandardInformation
.DeletePending
= FALSE
; /* FIXME */
1423 if (!(st
.st_mode
& (S_IWUSR
| S_IWGRP
| S_IWOTH
)))
1424 info
->BasicInformation
.FileAttributes
|= FILE_ATTRIBUTE_READONLY
;
1425 RtlSecondsSince1970ToTime( st
.st_mtime
, &info
->BasicInformation
.CreationTime
);
1426 RtlSecondsSince1970ToTime( st
.st_mtime
, &info
->BasicInformation
.LastWriteTime
);
1427 RtlSecondsSince1970ToTime( st
.st_ctime
, &info
->BasicInformation
.ChangeTime
);
1428 RtlSecondsSince1970ToTime( st
.st_atime
, &info
->BasicInformation
.LastAccessTime
);
1429 info
->InternalInformation
.IndexNumber
.QuadPart
= st
.st_ino
;
1430 info
->EaInformation
.EaSize
= 0;
1431 info
->AccessInformation
.AccessFlags
= 0; /* FIXME */
1432 info
->PositionInformation
.CurrentByteOffset
.QuadPart
= lseek( fd
, 0, SEEK_CUR
);
1433 info
->ModeInformation
.Mode
= 0; /* FIXME */
1434 info
->AlignmentInformation
.AlignmentRequirement
= 1; /* FIXME */
1435 info
->NameInformation
.FileNameLength
= 0;
1436 io
->Information
= sizeof(*info
) - sizeof(WCHAR
);
1440 case FileMailslotQueryInformation
:
1442 FILE_MAILSLOT_QUERY_INFORMATION
*info
= ptr
;
1444 SERVER_START_REQ( set_mailslot_info
)
1446 req
->handle
= hFile
;
1448 io
->u
.Status
= wine_server_call( req
);
1449 if( io
->u
.Status
== STATUS_SUCCESS
)
1451 info
->MaximumMessageSize
= reply
->max_msgsize
;
1452 info
->MailslotQuota
= 0;
1453 info
->NextMessageSize
= 0;
1454 info
->MessagesAvailable
= 0;
1455 info
->ReadTimeout
.QuadPart
= reply
->read_timeout
;
1462 ULONG size
= info
->MaximumMessageSize
? info
->MaximumMessageSize
: 0x10000;
1463 if (size
> 0x10000) size
= 0x10000;
1464 if ((tmpbuf
= RtlAllocateHeap( GetProcessHeap(), 0, size
)))
1466 int fd
, needs_close
;
1467 if (!server_get_unix_fd( hFile
, FILE_READ_DATA
, &fd
, &needs_close
, NULL
, NULL
))
1469 int res
= recv( fd
, tmpbuf
, size
, MSG_PEEK
);
1470 info
->MessagesAvailable
= (res
> 0);
1471 info
->NextMessageSize
= (res
>= 0) ? res
: MAILSLOT_NO_MESSAGE
;
1472 if (needs_close
) close( fd
);
1474 RtlFreeHeap( GetProcessHeap(), 0, tmpbuf
);
1479 case FilePipeLocalInformation
:
1481 FILE_PIPE_LOCAL_INFORMATION
* pli
= ptr
;
1483 SERVER_START_REQ( get_named_pipe_info
)
1485 req
->handle
= hFile
;
1486 if (!(io
->u
.Status
= wine_server_call( req
)))
1488 pli
->NamedPipeType
= (reply
->flags
& NAMED_PIPE_MESSAGE_STREAM_WRITE
) ?
1489 FILE_PIPE_TYPE_MESSAGE
: FILE_PIPE_TYPE_BYTE
;
1490 pli
->NamedPipeConfiguration
= 0; /* FIXME */
1491 pli
->MaximumInstances
= reply
->maxinstances
;
1492 pli
->CurrentInstances
= reply
->instances
;
1493 pli
->InboundQuota
= reply
->insize
;
1494 pli
->ReadDataAvailable
= 0; /* FIXME */
1495 pli
->OutboundQuota
= reply
->outsize
;
1496 pli
->WriteQuotaAvailable
= 0; /* FIXME */
1497 pli
->NamedPipeState
= 0; /* FIXME */
1498 pli
->NamedPipeEnd
= (reply
->flags
& NAMED_PIPE_SERVER_END
) ?
1499 FILE_PIPE_SERVER_END
: FILE_PIPE_CLIENT_END
;
1506 FIXME("Unsupported class (%d)\n", class);
1507 io
->u
.Status
= STATUS_NOT_IMPLEMENTED
;
1510 if (needs_close
) close( fd
);
1511 if (io
->u
.Status
== STATUS_SUCCESS
&& !io
->Information
) io
->Information
= info_sizes
[class];
1512 return io
->u
.Status
;
1515 /******************************************************************************
1516 * NtSetInformationFile [NTDLL.@]
1517 * ZwSetInformationFile [NTDLL.@]
1519 * Set information about an open file handle.
1522 * handle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
1523 * io [O] Receives information about the operation on return
1524 * ptr [I] Source for file information
1525 * len [I] Size of FileInformation
1526 * class [I] Type of file information to set
1529 * Success: 0. io is updated.
1530 * Failure: An NTSTATUS error code describing the error.
1532 NTSTATUS WINAPI
NtSetInformationFile(HANDLE handle
, PIO_STATUS_BLOCK io
,
1533 PVOID ptr
, ULONG len
, FILE_INFORMATION_CLASS
class)
1535 int fd
, needs_close
;
1537 TRACE("(%p,%p,%p,0x%08x,0x%08x)\n", handle
, io
, ptr
, len
, class);
1539 if ((io
->u
.Status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)))
1540 return io
->u
.Status
;
1542 io
->u
.Status
= STATUS_SUCCESS
;
1545 case FileBasicInformation
:
1546 if (len
>= sizeof(FILE_BASIC_INFORMATION
))
1549 const FILE_BASIC_INFORMATION
*info
= ptr
;
1551 if (info
->LastAccessTime
.QuadPart
|| info
->LastWriteTime
.QuadPart
)
1553 ULONGLONG sec
, nsec
;
1554 struct timeval tv
[2];
1556 if (!info
->LastAccessTime
.QuadPart
|| !info
->LastWriteTime
.QuadPart
)
1559 tv
[0].tv_sec
= tv
[0].tv_usec
= 0;
1560 tv
[1].tv_sec
= tv
[1].tv_usec
= 0;
1561 if (!fstat( fd
, &st
))
1563 tv
[0].tv_sec
= st
.st_atime
;
1564 tv
[1].tv_sec
= st
.st_mtime
;
1567 if (info
->LastAccessTime
.QuadPart
)
1569 sec
= RtlLargeIntegerDivide( info
->LastAccessTime
.QuadPart
, 10000000, &nsec
);
1570 tv
[0].tv_sec
= sec
- SECS_1601_TO_1970
;
1571 tv
[0].tv_usec
= (UINT
)nsec
/ 10;
1573 if (info
->LastWriteTime
.QuadPart
)
1575 sec
= RtlLargeIntegerDivide( info
->LastWriteTime
.QuadPart
, 10000000, &nsec
);
1576 tv
[1].tv_sec
= sec
- SECS_1601_TO_1970
;
1577 tv
[1].tv_usec
= (UINT
)nsec
/ 10;
1579 if (futimes( fd
, tv
) == -1) io
->u
.Status
= FILE_GetNtStatus();
1582 if (io
->u
.Status
== STATUS_SUCCESS
&& info
->FileAttributes
)
1584 if (fstat( fd
, &st
) == -1) io
->u
.Status
= FILE_GetNtStatus();
1587 if (info
->FileAttributes
& FILE_ATTRIBUTE_READONLY
)
1589 if (S_ISDIR( st
.st_mode
))
1590 WARN("FILE_ATTRIBUTE_READONLY ignored for directory.\n");
1592 st
.st_mode
&= ~0222; /* clear write permission bits */
1596 /* add write permission only where we already have read permission */
1597 st
.st_mode
|= (0600 | ((st
.st_mode
& 044) >> 1)) & (~FILE_umask
);
1599 if (fchmod( fd
, st
.st_mode
) == -1) io
->u
.Status
= FILE_GetNtStatus();
1603 else io
->u
.Status
= STATUS_INVALID_PARAMETER_3
;
1606 case FilePositionInformation
:
1607 if (len
>= sizeof(FILE_POSITION_INFORMATION
))
1609 const FILE_POSITION_INFORMATION
*info
= ptr
;
1611 if (lseek( fd
, info
->CurrentByteOffset
.QuadPart
, SEEK_SET
) == (off_t
)-1)
1612 io
->u
.Status
= FILE_GetNtStatus();
1614 else io
->u
.Status
= STATUS_INVALID_PARAMETER_3
;
1617 case FileEndOfFileInformation
:
1618 if (len
>= sizeof(FILE_END_OF_FILE_INFORMATION
))
1621 const FILE_END_OF_FILE_INFORMATION
*info
= ptr
;
1623 /* first try normal truncate */
1624 if (ftruncate( fd
, (off_t
)info
->EndOfFile
.QuadPart
) != -1) break;
1626 /* now check for the need to extend the file */
1627 if (fstat( fd
, &st
) != -1 && (off_t
)info
->EndOfFile
.QuadPart
> st
.st_size
)
1629 static const char zero
;
1631 /* extend the file one byte beyond the requested size and then truncate it */
1632 /* this should work around ftruncate implementations that can't extend files */
1633 if (pwrite( fd
, &zero
, 1, (off_t
)info
->EndOfFile
.QuadPart
) != -1 &&
1634 ftruncate( fd
, (off_t
)info
->EndOfFile
.QuadPart
) != -1) break;
1636 io
->u
.Status
= FILE_GetNtStatus();
1638 else io
->u
.Status
= STATUS_INVALID_PARAMETER_3
;
1641 case FileMailslotSetInformation
:
1643 FILE_MAILSLOT_SET_INFORMATION
*info
= ptr
;
1645 SERVER_START_REQ( set_mailslot_info
)
1647 req
->handle
= handle
;
1648 req
->flags
= MAILSLOT_SET_READ_TIMEOUT
;
1649 req
->read_timeout
= info
->ReadTimeout
.QuadPart
;
1650 io
->u
.Status
= wine_server_call( req
);
1657 FIXME("Unsupported class (%d)\n", class);
1658 io
->u
.Status
= STATUS_NOT_IMPLEMENTED
;
1661 if (needs_close
) close( fd
);
1662 io
->Information
= 0;
1663 return io
->u
.Status
;
1667 /******************************************************************************
1668 * NtQueryFullAttributesFile (NTDLL.@)
1670 NTSTATUS WINAPI
NtQueryFullAttributesFile( const OBJECT_ATTRIBUTES
*attr
,
1671 FILE_NETWORK_OPEN_INFORMATION
*info
)
1673 ANSI_STRING unix_name
;
1676 if (!(status
= wine_nt_to_unix_file_name( attr
->ObjectName
, &unix_name
, FILE_OPEN
,
1677 !(attr
->Attributes
& OBJ_CASE_INSENSITIVE
) )))
1681 if (stat( unix_name
.Buffer
, &st
) == -1)
1682 status
= FILE_GetNtStatus();
1683 else if (!S_ISREG(st
.st_mode
) && !S_ISDIR(st
.st_mode
))
1684 status
= STATUS_INVALID_INFO_CLASS
;
1687 if (S_ISDIR(st
.st_mode
))
1689 info
->FileAttributes
= FILE_ATTRIBUTE_DIRECTORY
;
1690 info
->AllocationSize
.QuadPart
= 0;
1691 info
->EndOfFile
.QuadPart
= 0;
1695 info
->FileAttributes
= FILE_ATTRIBUTE_ARCHIVE
;
1696 info
->AllocationSize
.QuadPart
= (ULONGLONG
)st
.st_blocks
* 512;
1697 info
->EndOfFile
.QuadPart
= st
.st_size
;
1699 if (!(st
.st_mode
& (S_IWUSR
| S_IWGRP
| S_IWOTH
)))
1700 info
->FileAttributes
|= FILE_ATTRIBUTE_READONLY
;
1701 RtlSecondsSince1970ToTime( st
.st_mtime
, &info
->CreationTime
);
1702 RtlSecondsSince1970ToTime( st
.st_mtime
, &info
->LastWriteTime
);
1703 RtlSecondsSince1970ToTime( st
.st_ctime
, &info
->ChangeTime
);
1704 RtlSecondsSince1970ToTime( st
.st_atime
, &info
->LastAccessTime
);
1705 if (DIR_is_hidden_file( attr
->ObjectName
))
1706 info
->FileAttributes
|= FILE_ATTRIBUTE_HIDDEN
;
1708 RtlFreeAnsiString( &unix_name
);
1710 else WARN("%s not found (%x)\n", debugstr_us(attr
->ObjectName
), status
);
1715 /******************************************************************************
1716 * NtQueryAttributesFile (NTDLL.@)
1717 * ZwQueryAttributesFile (NTDLL.@)
1719 NTSTATUS WINAPI
NtQueryAttributesFile( const OBJECT_ATTRIBUTES
*attr
, FILE_BASIC_INFORMATION
*info
)
1721 FILE_NETWORK_OPEN_INFORMATION full_info
;
1724 if (!(status
= NtQueryFullAttributesFile( attr
, &full_info
)))
1726 info
->CreationTime
.QuadPart
= full_info
.CreationTime
.QuadPart
;
1727 info
->LastAccessTime
.QuadPart
= full_info
.LastAccessTime
.QuadPart
;
1728 info
->LastWriteTime
.QuadPart
= full_info
.LastWriteTime
.QuadPart
;
1729 info
->ChangeTime
.QuadPart
= full_info
.ChangeTime
.QuadPart
;
1730 info
->FileAttributes
= full_info
.FileAttributes
;
1736 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__APPLE__)
1737 /* helper for FILE_GetDeviceInfo to hide some platform differences in fstatfs */
1738 static inline void get_device_info_fstatfs( FILE_FS_DEVICE_INFORMATION
*info
, const char *fstypename
,
1739 size_t fstypesize
, unsigned int flags
)
1741 if (!strncmp("cd9660", fstypename
, fstypesize
) ||
1742 !strncmp("udf", fstypename
, fstypesize
))
1744 info
->DeviceType
= FILE_DEVICE_CD_ROM_FILE_SYSTEM
;
1745 /* Don't assume read-only, let the mount options set it below */
1746 info
->Characteristics
|= FILE_REMOVABLE_MEDIA
;
1748 else if (!strncmp("nfs", fstypename
, fstypesize
) ||
1749 !strncmp("nwfs", fstypename
, fstypesize
) ||
1750 !strncmp("smbfs", fstypename
, fstypesize
) ||
1751 !strncmp("afpfs", fstypename
, fstypesize
))
1753 info
->DeviceType
= FILE_DEVICE_NETWORK_FILE_SYSTEM
;
1754 info
->Characteristics
|= FILE_REMOTE_DEVICE
;
1756 else if (!strncmp("procfs", fstypename
, fstypesize
))
1757 info
->DeviceType
= FILE_DEVICE_VIRTUAL_DISK
;
1759 info
->DeviceType
= FILE_DEVICE_DISK_FILE_SYSTEM
;
1761 if (flags
& MNT_RDONLY
)
1762 info
->Characteristics
|= FILE_READ_ONLY_DEVICE
;
1764 if (!(flags
& MNT_LOCAL
))
1766 info
->DeviceType
= FILE_DEVICE_NETWORK_FILE_SYSTEM
;
1767 info
->Characteristics
|= FILE_REMOTE_DEVICE
;
1772 /******************************************************************************
1775 * Implementation of the FileFsDeviceInformation query for NtQueryVolumeInformationFile.
1777 static NTSTATUS
get_device_info( int fd
, FILE_FS_DEVICE_INFORMATION
*info
)
1781 info
->Characteristics
= 0;
1782 if (fstat( fd
, &st
) < 0) return FILE_GetNtStatus();
1783 if (S_ISCHR( st
.st_mode
))
1785 info
->DeviceType
= FILE_DEVICE_UNKNOWN
;
1787 switch(major(st
.st_rdev
))
1790 info
->DeviceType
= FILE_DEVICE_NULL
;
1793 info
->DeviceType
= FILE_DEVICE_SERIAL_PORT
;
1796 info
->DeviceType
= FILE_DEVICE_PARALLEL_PORT
;
1798 case SCSI_TAPE_MAJOR
:
1799 info
->DeviceType
= FILE_DEVICE_TAPE
;
1804 else if (S_ISBLK( st
.st_mode
))
1806 info
->DeviceType
= FILE_DEVICE_DISK
;
1808 else if (S_ISFIFO( st
.st_mode
) || S_ISSOCK( st
.st_mode
))
1810 info
->DeviceType
= FILE_DEVICE_NAMED_PIPE
;
1812 else /* regular file or directory */
1814 #if defined(linux) && defined(HAVE_FSTATFS)
1817 /* check for floppy disk */
1818 if (major(st
.st_dev
) == FLOPPY_MAJOR
)
1819 info
->Characteristics
|= FILE_REMOVABLE_MEDIA
;
1821 if (fstatfs( fd
, &stfs
) < 0) stfs
.f_type
= 0;
1822 switch (stfs
.f_type
)
1824 case 0x9660: /* iso9660 */
1825 case 0x9fa1: /* supermount */
1826 case 0x15013346: /* udf */
1827 info
->DeviceType
= FILE_DEVICE_CD_ROM_FILE_SYSTEM
;
1828 info
->Characteristics
|= FILE_REMOVABLE_MEDIA
|FILE_READ_ONLY_DEVICE
;
1830 case 0x6969: /* nfs */
1831 case 0x517B: /* smbfs */
1832 case 0x564c: /* ncpfs */
1833 info
->DeviceType
= FILE_DEVICE_NETWORK_FILE_SYSTEM
;
1834 info
->Characteristics
|= FILE_REMOTE_DEVICE
;
1836 case 0x01021994: /* tmpfs */
1837 case 0x28cd3d45: /* cramfs */
1838 case 0x1373: /* devfs */
1839 case 0x9fa0: /* procfs */
1840 info
->DeviceType
= FILE_DEVICE_VIRTUAL_DISK
;
1843 info
->DeviceType
= FILE_DEVICE_DISK_FILE_SYSTEM
;
1846 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__)
1849 if (fstatfs( fd
, &stfs
) < 0)
1850 info
->DeviceType
= FILE_DEVICE_DISK_FILE_SYSTEM
;
1852 get_device_info_fstatfs( info
, stfs
.f_fstypename
,
1853 sizeof(stfs
.f_fstypename
), stfs
.f_flags
);
1854 #elif defined(__NetBSD__)
1855 struct statvfs stfs
;
1857 if (fstatvfs( fd
, &stfs
) < 0)
1858 info
->DeviceType
= FILE_DEVICE_DISK_FILE_SYSTEM
;
1860 get_device_info_fstatfs( info
, stfs
.f_fstypename
,
1861 sizeof(stfs
.f_fstypename
), stfs
.f_flag
);
1863 /* Use dkio to work out device types */
1865 # include <sys/dkio.h>
1866 # include <sys/vtoc.h>
1867 struct dk_cinfo dkinf
;
1868 int retval
= ioctl(fd
, DKIOCINFO
, &dkinf
);
1870 WARN("Unable to get disk device type information - assuming a disk like device\n");
1871 info
->DeviceType
= FILE_DEVICE_DISK_FILE_SYSTEM
;
1873 switch (dkinf
.dki_ctype
)
1876 info
->DeviceType
= FILE_DEVICE_CD_ROM_FILE_SYSTEM
;
1877 info
->Characteristics
|= FILE_REMOVABLE_MEDIA
|FILE_READ_ONLY_DEVICE
;
1881 case DKC_INTEL82072
:
1882 case DKC_INTEL82077
:
1883 info
->DeviceType
= FILE_DEVICE_DISK_FILE_SYSTEM
;
1884 info
->Characteristics
|= FILE_REMOVABLE_MEDIA
;
1887 info
->DeviceType
= FILE_DEVICE_VIRTUAL_DISK
;
1890 info
->DeviceType
= FILE_DEVICE_DISK_FILE_SYSTEM
;
1895 if (!warned
++) FIXME( "device info not properly supported on this platform\n" );
1896 info
->DeviceType
= FILE_DEVICE_DISK_FILE_SYSTEM
;
1898 info
->Characteristics
|= FILE_DEVICE_IS_MOUNTED
;
1900 return STATUS_SUCCESS
;
1904 /******************************************************************************
1905 * NtQueryVolumeInformationFile [NTDLL.@]
1906 * ZwQueryVolumeInformationFile [NTDLL.@]
1908 * Get volume information for an open file handle.
1911 * handle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
1912 * io [O] Receives information about the operation on return
1913 * buffer [O] Destination for volume information
1914 * length [I] Size of FsInformation
1915 * info_class [I] Type of volume information to set
1918 * Success: 0. io and buffer are updated.
1919 * Failure: An NTSTATUS error code describing the error.
1921 NTSTATUS WINAPI
NtQueryVolumeInformationFile( HANDLE handle
, PIO_STATUS_BLOCK io
,
1922 PVOID buffer
, ULONG length
,
1923 FS_INFORMATION_CLASS info_class
)
1925 int fd
, needs_close
;
1928 if ((io
->u
.Status
= server_get_unix_fd( handle
, 0, &fd
, &needs_close
, NULL
, NULL
)) != STATUS_SUCCESS
)
1929 return io
->u
.Status
;
1931 io
->u
.Status
= STATUS_NOT_IMPLEMENTED
;
1932 io
->Information
= 0;
1934 switch( info_class
)
1936 case FileFsVolumeInformation
:
1937 FIXME( "%p: volume info not supported\n", handle
);
1939 case FileFsLabelInformation
:
1940 FIXME( "%p: label info not supported\n", handle
);
1942 case FileFsSizeInformation
:
1943 if (length
< sizeof(FILE_FS_SIZE_INFORMATION
))
1944 io
->u
.Status
= STATUS_BUFFER_TOO_SMALL
;
1947 FILE_FS_SIZE_INFORMATION
*info
= buffer
;
1949 if (fstat( fd
, &st
) < 0)
1951 io
->u
.Status
= FILE_GetNtStatus();
1954 if (!S_ISREG(st
.st_mode
) && !S_ISDIR(st
.st_mode
))
1956 io
->u
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
1960 /* Linux's fstatvfs is buggy */
1961 #if !defined(linux) || !defined(HAVE_FSTATFS)
1962 struct statvfs stfs
;
1964 if (fstatvfs( fd
, &stfs
) < 0)
1966 io
->u
.Status
= FILE_GetNtStatus();
1969 info
->BytesPerSector
= stfs
.f_frsize
;
1972 if (fstatfs( fd
, &stfs
) < 0)
1974 io
->u
.Status
= FILE_GetNtStatus();
1977 info
->BytesPerSector
= stfs
.f_bsize
;
1979 info
->TotalAllocationUnits
.QuadPart
= stfs
.f_blocks
;
1980 info
->AvailableAllocationUnits
.QuadPart
= stfs
.f_bavail
;
1981 info
->SectorsPerAllocationUnit
= 1;
1982 io
->Information
= sizeof(*info
);
1983 io
->u
.Status
= STATUS_SUCCESS
;
1987 case FileFsDeviceInformation
:
1988 if (length
< sizeof(FILE_FS_DEVICE_INFORMATION
))
1989 io
->u
.Status
= STATUS_BUFFER_TOO_SMALL
;
1992 FILE_FS_DEVICE_INFORMATION
*info
= buffer
;
1994 if ((io
->u
.Status
= get_device_info( fd
, info
)) == STATUS_SUCCESS
)
1995 io
->Information
= sizeof(*info
);
1998 case FileFsAttributeInformation
:
1999 FIXME( "%p: attribute info not supported\n", handle
);
2001 case FileFsControlInformation
:
2002 FIXME( "%p: control info not supported\n", handle
);
2004 case FileFsFullSizeInformation
:
2005 FIXME( "%p: full size info not supported\n", handle
);
2007 case FileFsObjectIdInformation
:
2008 FIXME( "%p: object id info not supported\n", handle
);
2010 case FileFsMaximumInformation
:
2011 FIXME( "%p: maximum info not supported\n", handle
);
2014 io
->u
.Status
= STATUS_INVALID_PARAMETER
;
2017 if (needs_close
) close( fd
);
2018 return io
->u
.Status
;
2022 /******************************************************************
2023 * NtFlushBuffersFile (NTDLL.@)
2025 * Flush any buffered data on an open file handle.
2028 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
2029 * IoStatusBlock [O] Receives information about the operation on return
2032 * Success: 0. IoStatusBlock is updated.
2033 * Failure: An NTSTATUS error code describing the error.
2035 NTSTATUS WINAPI
NtFlushBuffersFile( HANDLE hFile
, IO_STATUS_BLOCK
* IoStatusBlock
)
2038 HANDLE hEvent
= NULL
;
2040 SERVER_START_REQ( flush_file
)
2042 req
->handle
= hFile
;
2043 ret
= wine_server_call( req
);
2044 hEvent
= reply
->event
;
2049 ret
= NtWaitForSingleObject( hEvent
, FALSE
, NULL
);
2055 /******************************************************************
2056 * NtLockFile (NTDLL.@)
2060 NTSTATUS WINAPI
NtLockFile( HANDLE hFile
, HANDLE lock_granted_event
,
2061 PIO_APC_ROUTINE apc
, void* apc_user
,
2062 PIO_STATUS_BLOCK io_status
, PLARGE_INTEGER offset
,
2063 PLARGE_INTEGER count
, ULONG
* key
, BOOLEAN dont_wait
,
2070 if (apc
|| io_status
|| key
)
2072 FIXME("Unimplemented yet parameter\n");
2073 return STATUS_NOT_IMPLEMENTED
;
2078 SERVER_START_REQ( lock_file
)
2080 req
->handle
= hFile
;
2081 req
->offset_low
= offset
->u
.LowPart
;
2082 req
->offset_high
= offset
->u
.HighPart
;
2083 req
->count_low
= count
->u
.LowPart
;
2084 req
->count_high
= count
->u
.HighPart
;
2085 req
->shared
= !exclusive
;
2086 req
->wait
= !dont_wait
;
2087 ret
= wine_server_call( req
);
2088 handle
= reply
->handle
;
2089 async
= reply
->overlapped
;
2092 if (ret
!= STATUS_PENDING
)
2094 if (!ret
&& lock_granted_event
) NtSetEvent(lock_granted_event
, NULL
);
2100 FIXME( "Async I/O lock wait not implemented, might deadlock\n" );
2101 if (handle
) NtClose( handle
);
2102 return STATUS_PENDING
;
2106 NtWaitForSingleObject( handle
, FALSE
, NULL
);
2113 /* Unix lock conflict, sleep a bit and retry */
2114 time
.QuadPart
= 100 * (ULONGLONG
)10000;
2115 time
.QuadPart
= -time
.QuadPart
;
2116 NtDelayExecution( FALSE
, &time
);
2122 /******************************************************************
2123 * NtUnlockFile (NTDLL.@)
2127 NTSTATUS WINAPI
NtUnlockFile( HANDLE hFile
, PIO_STATUS_BLOCK io_status
,
2128 PLARGE_INTEGER offset
, PLARGE_INTEGER count
,
2133 TRACE( "%p %x%08x %x%08x\n",
2134 hFile
, offset
->u
.HighPart
, offset
->u
.LowPart
, count
->u
.HighPart
, count
->u
.LowPart
);
2136 if (io_status
|| key
)
2138 FIXME("Unimplemented yet parameter\n");
2139 return STATUS_NOT_IMPLEMENTED
;
2142 SERVER_START_REQ( unlock_file
)
2144 req
->handle
= hFile
;
2145 req
->offset_low
= offset
->u
.LowPart
;
2146 req
->offset_high
= offset
->u
.HighPart
;
2147 req
->count_low
= count
->u
.LowPart
;
2148 req
->count_high
= count
->u
.HighPart
;
2149 status
= wine_server_call( req
);
2155 /******************************************************************
2156 * NtCreateNamedPipeFile (NTDLL.@)
2160 NTSTATUS WINAPI
NtCreateNamedPipeFile( PHANDLE handle
, ULONG access
,
2161 POBJECT_ATTRIBUTES attr
, PIO_STATUS_BLOCK iosb
,
2162 ULONG sharing
, ULONG dispo
, ULONG options
,
2163 ULONG pipe_type
, ULONG read_mode
,
2164 ULONG completion_mode
, ULONG max_inst
,
2165 ULONG inbound_quota
, ULONG outbound_quota
,
2166 PLARGE_INTEGER timeout
)
2170 TRACE("(%p %x %s %p %x %d %x %d %d %d %d %d %d %p)\n",
2171 handle
, access
, debugstr_w(attr
->ObjectName
->Buffer
), iosb
, sharing
, dispo
,
2172 options
, pipe_type
, read_mode
, completion_mode
, max_inst
, inbound_quota
,
2173 outbound_quota
, timeout
);
2175 /* assume we only get relative timeout */
2176 if (timeout
->QuadPart
> 0)
2177 FIXME("Wrong time %s\n", wine_dbgstr_longlong(timeout
->QuadPart
));
2179 SERVER_START_REQ( create_named_pipe
)
2181 req
->access
= access
;
2182 req
->attributes
= attr
->Attributes
;
2183 req
->rootdir
= attr
->RootDirectory
;
2184 req
->options
= options
;
2186 (pipe_type
) ? NAMED_PIPE_MESSAGE_STREAM_WRITE
: 0 |
2187 (read_mode
) ? NAMED_PIPE_MESSAGE_STREAM_READ
: 0 |
2188 (completion_mode
) ? NAMED_PIPE_NONBLOCKING_MODE
: 0;
2189 req
->maxinstances
= max_inst
;
2190 req
->outsize
= outbound_quota
;
2191 req
->insize
= inbound_quota
;
2192 req
->timeout
= timeout
->QuadPart
;
2193 wine_server_add_data( req
, attr
->ObjectName
->Buffer
,
2194 attr
->ObjectName
->Length
);
2195 status
= wine_server_call( req
);
2196 if (!status
) *handle
= reply
->handle
;
2202 /******************************************************************
2203 * NtDeleteFile (NTDLL.@)
2207 NTSTATUS WINAPI
NtDeleteFile( POBJECT_ATTRIBUTES ObjectAttributes
)
2213 TRACE("%p\n", ObjectAttributes
);
2214 status
= NtCreateFile( &hFile
, GENERIC_READ
| GENERIC_WRITE
| DELETE
,
2215 ObjectAttributes
, &io
, NULL
, 0,
2216 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
2217 FILE_OPEN
, FILE_DELETE_ON_CLOSE
, NULL
, 0 );
2218 if (status
== STATUS_SUCCESS
) status
= NtClose(hFile
);
2222 /******************************************************************
2223 * NtCancelIoFile (NTDLL.@)
2227 NTSTATUS WINAPI
NtCancelIoFile( HANDLE hFile
, PIO_STATUS_BLOCK io_status
)
2229 LARGE_INTEGER timeout
;
2231 TRACE("%p %p\n", hFile
, io_status
);
2233 SERVER_START_REQ( cancel_async
)
2235 req
->handle
= hFile
;
2236 wine_server_call( req
);
2239 /* Let some APC be run, so that we can run the remaining APCs on hFile
2240 * either the cancelation of the pending one, but also the execution
2241 * of the queued APC, but not yet run. This is needed to ensure proper
2242 * clean-up of allocated data.
2244 timeout
.u
.LowPart
= timeout
.u
.HighPart
= 0;
2245 return io_status
->u
.Status
= NtDelayExecution( TRUE
, &timeout
);
2248 /******************************************************************************
2249 * NtCreateMailslotFile [NTDLL.@]
2250 * ZwCreateMailslotFile [NTDLL.@]
2253 * pHandle [O] pointer to receive the handle created
2254 * DesiredAccess [I] access mode (read, write, etc)
2255 * ObjectAttributes [I] fully qualified NT path of the mailslot
2256 * IoStatusBlock [O] receives completion status and other info
2259 * MaxMessageSize [I]
2265 NTSTATUS WINAPI
NtCreateMailslotFile(PHANDLE pHandle
, ULONG DesiredAccess
,
2266 POBJECT_ATTRIBUTES attr
, PIO_STATUS_BLOCK IoStatusBlock
,
2267 ULONG CreateOptions
, ULONG MailslotQuota
, ULONG MaxMessageSize
,
2268 PLARGE_INTEGER TimeOut
)
2270 LARGE_INTEGER timeout
;
2273 TRACE("%p %08x %p %p %08x %08x %08x %p\n",
2274 pHandle
, DesiredAccess
, attr
, IoStatusBlock
,
2275 CreateOptions
, MailslotQuota
, MaxMessageSize
, TimeOut
);
2277 if (!pHandle
) return STATUS_ACCESS_VIOLATION
;
2278 if (!attr
) return STATUS_INVALID_PARAMETER
;
2279 if (!attr
->ObjectName
) return STATUS_OBJECT_PATH_SYNTAX_BAD
;
2282 * For a NULL TimeOut pointer set the default timeout value
2285 timeout
.QuadPart
= -1;
2287 timeout
.QuadPart
= TimeOut
->QuadPart
;
2289 SERVER_START_REQ( create_mailslot
)
2291 req
->access
= DesiredAccess
;
2292 req
->attributes
= attr
->Attributes
;
2293 req
->rootdir
= attr
->RootDirectory
;
2294 req
->max_msgsize
= MaxMessageSize
;
2295 req
->read_timeout
= timeout
.QuadPart
;
2296 wine_server_add_data( req
, attr
->ObjectName
->Buffer
,
2297 attr
->ObjectName
->Length
);
2298 ret
= wine_server_call( req
);
2299 if( ret
== STATUS_SUCCESS
)
2300 *pHandle
= reply
->handle
;