mmdevapi: Fix compiler warnings with flag -Wcast-qual.
[wine.git] / dlls / ntdll / file.c
blob741395ddbd2d22df8fb44cd353df796c2b5e0427
1 /*
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
19 #include "config.h"
20 #include "wine/port.h"
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_SYS_IOCTL_H
46 #include <sys/ioctl.h>
47 #endif
48 #ifdef HAVE_SYS_FILIO_H
49 # include <sys/filio.h>
50 #endif
51 #ifdef HAVE_POLL_H
52 #include <poll.h>
53 #endif
54 #ifdef HAVE_SYS_POLL_H
55 #include <sys/poll.h>
56 #endif
57 #ifdef HAVE_SYS_SOCKET_H
58 #include <sys/socket.h>
59 #endif
60 #ifdef HAVE_UTIME_H
61 # include <utime.h>
62 #endif
63 #ifdef HAVE_SYS_VFS_H
64 # include <sys/vfs.h>
65 #endif
66 #ifdef HAVE_SYS_MOUNT_H
67 # include <sys/mount.h>
68 #endif
69 #ifdef HAVE_SYS_STATFS_H
70 # include <sys/statfs.h>
71 #endif
72 #ifdef HAVE_VALGRIND_MEMCHECK_H
73 # include <valgrind/memcheck.h>
74 #endif
76 #define NONAMELESSUNION
77 #define NONAMELESSSTRUCT
78 #include "ntstatus.h"
79 #define WIN32_NO_STATUS
80 #include "wine/unicode.h"
81 #include "wine/debug.h"
82 #include "wine/server.h"
83 #include "ntdll_misc.h"
85 #include "winternl.h"
86 #include "winioctl.h"
87 #include "ddk/ntddser.h"
89 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
91 mode_t FILE_umask = 0;
93 #define SECSPERDAY 86400
94 #define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY)
97 /**************************************************************************
98 * FILE_CreateFile (internal)
99 * Open a file.
101 * Parameter set fully identical with NtCreateFile
103 static NTSTATUS FILE_CreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATTRIBUTES attr,
104 PIO_STATUS_BLOCK io, PLARGE_INTEGER alloc_size,
105 ULONG attributes, ULONG sharing, ULONG disposition,
106 ULONG options, PVOID ea_buffer, ULONG ea_length )
108 ANSI_STRING unix_name;
109 int created = FALSE;
111 TRACE("handle=%p access=%08x name=%s objattr=%08x root=%p sec=%p io=%p alloc_size=%p "
112 "attr=%08x sharing=%08x disp=%d options=%08x ea=%p.0x%08x\n",
113 handle, access, debugstr_us(attr->ObjectName), attr->Attributes,
114 attr->RootDirectory, attr->SecurityDescriptor, io, alloc_size,
115 attributes, sharing, disposition, options, ea_buffer, ea_length );
117 if (!attr || !attr->ObjectName) return STATUS_INVALID_PARAMETER;
119 if (alloc_size) FIXME( "alloc_size not supported\n" );
121 if (options & FILE_OPEN_BY_FILE_ID)
122 io->u.Status = file_id_to_unix_file_name( attr, &unix_name );
123 else
124 io->u.Status = nt_to_unix_file_name_attr( attr, &unix_name, disposition );
126 if (io->u.Status == STATUS_BAD_DEVICE_TYPE)
128 SERVER_START_REQ( open_file_object )
130 req->access = access;
131 req->attributes = attr->Attributes;
132 req->rootdir = wine_server_obj_handle( attr->RootDirectory );
133 req->sharing = sharing;
134 req->options = options;
135 wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
136 io->u.Status = wine_server_call( req );
137 *handle = wine_server_ptr_handle( reply->handle );
139 SERVER_END_REQ;
140 if (io->u.Status == STATUS_SUCCESS) io->Information = FILE_OPENED;
141 return io->u.Status;
144 if (io->u.Status == STATUS_NO_SUCH_FILE &&
145 disposition != FILE_OPEN && disposition != FILE_OVERWRITE)
147 created = TRUE;
148 io->u.Status = STATUS_SUCCESS;
151 if (io->u.Status == STATUS_SUCCESS)
153 struct security_descriptor *sd;
154 struct object_attributes objattr;
156 objattr.rootdir = wine_server_obj_handle( attr->RootDirectory );
157 objattr.name_len = 0;
158 io->u.Status = NTDLL_create_struct_sd( attr->SecurityDescriptor, &sd, &objattr.sd_len );
159 if (io->u.Status != STATUS_SUCCESS)
161 RtlFreeAnsiString( &unix_name );
162 return io->u.Status;
165 SERVER_START_REQ( create_file )
167 req->access = access;
168 req->attributes = attr->Attributes;
169 req->sharing = sharing;
170 req->create = disposition;
171 req->options = options;
172 req->attrs = attributes;
173 wine_server_add_data( req, &objattr, sizeof(objattr) );
174 if (objattr.sd_len) wine_server_add_data( req, sd, objattr.sd_len );
175 wine_server_add_data( req, unix_name.Buffer, unix_name.Length );
176 io->u.Status = wine_server_call( req );
177 *handle = wine_server_ptr_handle( reply->handle );
179 SERVER_END_REQ;
180 NTDLL_free_struct_sd( sd );
181 RtlFreeAnsiString( &unix_name );
183 else WARN("%s not found (%x)\n", debugstr_us(attr->ObjectName), io->u.Status );
185 if (io->u.Status == STATUS_SUCCESS)
187 if (created) io->Information = FILE_CREATED;
188 else switch(disposition)
190 case FILE_SUPERSEDE:
191 io->Information = FILE_SUPERSEDED;
192 break;
193 case FILE_CREATE:
194 io->Information = FILE_CREATED;
195 break;
196 case FILE_OPEN:
197 case FILE_OPEN_IF:
198 io->Information = FILE_OPENED;
199 break;
200 case FILE_OVERWRITE:
201 case FILE_OVERWRITE_IF:
202 io->Information = FILE_OVERWRITTEN;
203 break;
207 return io->u.Status;
210 /**************************************************************************
211 * NtOpenFile [NTDLL.@]
212 * ZwOpenFile [NTDLL.@]
214 * Open a file.
216 * PARAMS
217 * handle [O] Variable that receives the file handle on return
218 * access [I] Access desired by the caller to the file
219 * attr [I] Structure describing the file to be opened
220 * io [O] Receives details about the result of the operation
221 * sharing [I] Type of shared access the caller requires
222 * options [I] Options for the file open
224 * RETURNS
225 * Success: 0. FileHandle and IoStatusBlock are updated.
226 * Failure: An NTSTATUS error code describing the error.
228 NTSTATUS WINAPI NtOpenFile( PHANDLE handle, ACCESS_MASK access,
229 POBJECT_ATTRIBUTES attr, PIO_STATUS_BLOCK io,
230 ULONG sharing, ULONG options )
232 return FILE_CreateFile( handle, access, attr, io, NULL, 0,
233 sharing, FILE_OPEN, options, NULL, 0 );
236 /**************************************************************************
237 * NtCreateFile [NTDLL.@]
238 * ZwCreateFile [NTDLL.@]
240 * Either create a new file or directory, or open an existing file, device,
241 * directory or volume.
243 * PARAMS
244 * handle [O] Points to a variable which receives the file handle on return
245 * access [I] Desired access to the file
246 * attr [I] Structure describing the file
247 * io [O] Receives information about the operation on return
248 * alloc_size [I] Initial size of the file in bytes
249 * attributes [I] Attributes to create the file with
250 * sharing [I] Type of shared access the caller would like to the file
251 * disposition [I] Specifies what to do, depending on whether the file already exists
252 * options [I] Options for creating a new file
253 * ea_buffer [I] Pointer to an extended attributes buffer
254 * ea_length [I] Length of ea_buffer
256 * RETURNS
257 * Success: 0. handle and io are updated.
258 * Failure: An NTSTATUS error code describing the error.
260 NTSTATUS WINAPI NtCreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATTRIBUTES attr,
261 PIO_STATUS_BLOCK io, PLARGE_INTEGER alloc_size,
262 ULONG attributes, ULONG sharing, ULONG disposition,
263 ULONG options, PVOID ea_buffer, ULONG ea_length )
265 return FILE_CreateFile( handle, access, attr, io, alloc_size, attributes,
266 sharing, disposition, options, ea_buffer, ea_length );
269 /***********************************************************************
270 * Asynchronous file I/O *
273 struct async_fileio
275 HANDLE handle;
276 PIO_APC_ROUTINE apc;
277 void *apc_arg;
280 typedef struct
282 struct async_fileio io;
283 char* buffer;
284 unsigned int already;
285 unsigned int count;
286 BOOL avail_mode;
287 } async_fileio_read;
289 typedef struct
291 struct async_fileio io;
292 const char *buffer;
293 unsigned int already;
294 unsigned int count;
295 } async_fileio_write;
298 /* callback for file I/O user APC */
299 static void WINAPI fileio_apc( void *arg, IO_STATUS_BLOCK *io, ULONG reserved )
301 struct async_fileio *async = arg;
302 if (async->apc) async->apc( async->apc_arg, io, reserved );
303 RtlFreeHeap( GetProcessHeap(), 0, async );
306 /***********************************************************************
307 * FILE_GetNtStatus(void)
309 * Retrieve the Nt Status code from errno.
310 * Try to be consistent with FILE_SetDosError().
312 NTSTATUS FILE_GetNtStatus(void)
314 int err = errno;
316 TRACE( "errno = %d\n", errno );
317 switch (err)
319 case EAGAIN: return STATUS_SHARING_VIOLATION;
320 case EBADF: return STATUS_INVALID_HANDLE;
321 case EBUSY: return STATUS_DEVICE_BUSY;
322 case ENOSPC: return STATUS_DISK_FULL;
323 case EPERM:
324 case EROFS:
325 case EACCES: return STATUS_ACCESS_DENIED;
326 case ENOTDIR: return STATUS_OBJECT_PATH_NOT_FOUND;
327 case ENOENT: return STATUS_OBJECT_NAME_NOT_FOUND;
328 case EISDIR: return STATUS_FILE_IS_A_DIRECTORY;
329 case EMFILE:
330 case ENFILE: return STATUS_TOO_MANY_OPENED_FILES;
331 case EINVAL: return STATUS_INVALID_PARAMETER;
332 case ENOTEMPTY: return STATUS_DIRECTORY_NOT_EMPTY;
333 case EPIPE: return STATUS_PIPE_DISCONNECTED;
334 case EIO: return STATUS_DEVICE_NOT_READY;
335 #ifdef ENOMEDIUM
336 case ENOMEDIUM: return STATUS_NO_MEDIA_IN_DEVICE;
337 #endif
338 case ENXIO: return STATUS_NO_SUCH_DEVICE;
339 case ENOTTY:
340 case EOPNOTSUPP:return STATUS_NOT_SUPPORTED;
341 case ECONNRESET:return STATUS_PIPE_DISCONNECTED;
342 case EFAULT: return STATUS_ACCESS_VIOLATION;
343 case ESPIPE: return STATUS_ILLEGAL_FUNCTION;
344 case ENOEXEC: /* ?? */
345 case EEXIST: /* ?? */
346 default:
347 FIXME( "Converting errno %d to STATUS_UNSUCCESSFUL\n", err );
348 return STATUS_UNSUCCESSFUL;
352 /***********************************************************************
353 * FILE_AsyncReadService (INTERNAL)
355 static NTSTATUS FILE_AsyncReadService(void *user, PIO_STATUS_BLOCK iosb, NTSTATUS status, void **apc)
357 async_fileio_read *fileio = user;
358 int fd, needs_close, result;
360 switch (status)
362 case STATUS_ALERTED: /* got some new data */
363 /* check to see if the data is ready (non-blocking) */
364 if ((status = server_get_unix_fd( fileio->io.handle, FILE_READ_DATA, &fd,
365 &needs_close, NULL, NULL )))
366 break;
368 result = read(fd, &fileio->buffer[fileio->already], fileio->count - fileio->already);
369 if (needs_close) close( fd );
371 if (result < 0)
373 if (errno == EAGAIN || errno == EINTR)
374 status = STATUS_PENDING;
375 else /* check to see if the transfer is complete */
376 status = FILE_GetNtStatus();
378 else if (result == 0)
380 status = fileio->already ? STATUS_SUCCESS : STATUS_PIPE_BROKEN;
382 else
384 fileio->already += result;
385 if (fileio->already >= fileio->count || fileio->avail_mode)
386 status = STATUS_SUCCESS;
387 else
389 /* if we only have to read the available data, and none is available,
390 * simply cancel the request. If data was available, it has been read
391 * while in by previous call (NtDelayExecution)
393 status = (fileio->avail_mode) ? STATUS_SUCCESS : STATUS_PENDING;
396 break;
398 case STATUS_TIMEOUT:
399 case STATUS_IO_TIMEOUT:
400 if (fileio->already) status = STATUS_SUCCESS;
401 break;
403 if (status != STATUS_PENDING)
405 iosb->u.Status = status;
406 iosb->Information = fileio->already;
407 *apc = fileio_apc;
409 return status;
412 struct io_timeouts
414 int interval; /* max interval between two bytes */
415 int total; /* total timeout for the whole operation */
416 int end_time; /* absolute time of end of operation */
419 /* retrieve the I/O timeouts to use for a given handle */
420 static NTSTATUS get_io_timeouts( HANDLE handle, enum server_fd_type type, ULONG count, BOOL is_read,
421 struct io_timeouts *timeouts )
423 NTSTATUS status = STATUS_SUCCESS;
425 timeouts->interval = timeouts->total = -1;
427 switch(type)
429 case FD_TYPE_SERIAL:
431 /* GetCommTimeouts */
432 SERIAL_TIMEOUTS st;
433 IO_STATUS_BLOCK io;
435 status = NtDeviceIoControlFile( handle, NULL, NULL, NULL, &io,
436 IOCTL_SERIAL_GET_TIMEOUTS, NULL, 0, &st, sizeof(st) );
437 if (status) break;
439 if (is_read)
441 if (st.ReadIntervalTimeout)
442 timeouts->interval = st.ReadIntervalTimeout;
444 if (st.ReadTotalTimeoutMultiplier || st.ReadTotalTimeoutConstant)
446 timeouts->total = st.ReadTotalTimeoutConstant;
447 if (st.ReadTotalTimeoutMultiplier != MAXDWORD)
448 timeouts->total += count * st.ReadTotalTimeoutMultiplier;
450 else if (st.ReadIntervalTimeout == MAXDWORD)
451 timeouts->interval = timeouts->total = 0;
453 else /* write */
455 if (st.WriteTotalTimeoutMultiplier || st.WriteTotalTimeoutConstant)
457 timeouts->total = st.WriteTotalTimeoutConstant;
458 if (st.WriteTotalTimeoutMultiplier != MAXDWORD)
459 timeouts->total += count * st.WriteTotalTimeoutMultiplier;
463 break;
464 case FD_TYPE_MAILSLOT:
465 if (is_read)
467 timeouts->interval = 0; /* return as soon as we got something */
468 SERVER_START_REQ( set_mailslot_info )
470 req->handle = wine_server_obj_handle( handle );
471 req->flags = 0;
472 if (!(status = wine_server_call( req )) &&
473 reply->read_timeout != TIMEOUT_INFINITE)
474 timeouts->total = reply->read_timeout / -10000;
476 SERVER_END_REQ;
478 break;
479 case FD_TYPE_SOCKET:
480 case FD_TYPE_PIPE:
481 case FD_TYPE_CHAR:
482 if (is_read) timeouts->interval = 0; /* return as soon as we got something */
483 break;
484 default:
485 break;
487 if (timeouts->total != -1) timeouts->end_time = NtGetTickCount() + timeouts->total;
488 return STATUS_SUCCESS;
492 /* retrieve the timeout for the next wait, in milliseconds */
493 static inline int get_next_io_timeout( const struct io_timeouts *timeouts, ULONG already )
495 int ret = -1;
497 if (timeouts->total != -1)
499 ret = timeouts->end_time - NtGetTickCount();
500 if (ret < 0) ret = 0;
502 if (already && timeouts->interval != -1)
504 if (ret == -1 || ret > timeouts->interval) ret = timeouts->interval;
506 return ret;
510 /* retrieve the avail_mode flag for async reads */
511 static NTSTATUS get_io_avail_mode( HANDLE handle, enum server_fd_type type, BOOL *avail_mode )
513 NTSTATUS status = STATUS_SUCCESS;
515 switch(type)
517 case FD_TYPE_SERIAL:
519 /* GetCommTimeouts */
520 SERIAL_TIMEOUTS st;
521 IO_STATUS_BLOCK io;
523 status = NtDeviceIoControlFile( handle, NULL, NULL, NULL, &io,
524 IOCTL_SERIAL_GET_TIMEOUTS, NULL, 0, &st, sizeof(st) );
525 if (status) break;
526 *avail_mode = (!st.ReadTotalTimeoutMultiplier &&
527 !st.ReadTotalTimeoutConstant &&
528 st.ReadIntervalTimeout == MAXDWORD);
530 break;
531 case FD_TYPE_MAILSLOT:
532 case FD_TYPE_SOCKET:
533 case FD_TYPE_PIPE:
534 case FD_TYPE_CHAR:
535 *avail_mode = TRUE;
536 break;
537 default:
538 *avail_mode = FALSE;
539 break;
541 return status;
545 /******************************************************************************
546 * NtReadFile [NTDLL.@]
547 * ZwReadFile [NTDLL.@]
549 * Read from an open file handle.
551 * PARAMS
552 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
553 * Event [I] Event to signal upon completion (or NULL)
554 * ApcRoutine [I] Callback to call upon completion (or NULL)
555 * ApcContext [I] Context for ApcRoutine (or NULL)
556 * IoStatusBlock [O] Receives information about the operation on return
557 * Buffer [O] Destination for the data read
558 * Length [I] Size of Buffer
559 * ByteOffset [O] Destination for the new file pointer position (or NULL)
560 * Key [O] Function unknown (may be NULL)
562 * RETURNS
563 * Success: 0. IoStatusBlock is updated, and the Information member contains
564 * The number of bytes read.
565 * Failure: An NTSTATUS error code describing the error.
567 NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
568 PIO_APC_ROUTINE apc, void* apc_user,
569 PIO_STATUS_BLOCK io_status, void* buffer, ULONG length,
570 PLARGE_INTEGER offset, PULONG key)
572 int result, unix_handle, needs_close, timeout_init_done = 0;
573 unsigned int options;
574 struct io_timeouts timeouts;
575 NTSTATUS status;
576 ULONG total = 0;
577 enum server_fd_type type;
578 ULONG_PTR cvalue = apc ? 0 : (ULONG_PTR)apc_user;
580 TRACE("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%p),partial stub!\n",
581 hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
583 if (!io_status) return STATUS_ACCESS_VIOLATION;
585 status = server_get_unix_fd( hFile, FILE_READ_DATA, &unix_handle,
586 &needs_close, &type, &options );
587 if (status) return status;
589 if (!virtual_check_buffer_for_write( buffer, length ))
591 status = STATUS_ACCESS_VIOLATION;
592 goto done;
595 if (type == FD_TYPE_FILE && offset && offset->QuadPart != (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */ )
597 /* async I/O doesn't make sense on regular files */
598 while ((result = pread( unix_handle, buffer, length, offset->QuadPart )) == -1)
600 if (errno != EINTR)
602 status = FILE_GetNtStatus();
603 goto done;
606 if (options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT))
607 /* update file pointer position */
608 lseek( unix_handle, offset->QuadPart + result, SEEK_SET );
610 total = result;
611 status = total ? STATUS_SUCCESS : STATUS_END_OF_FILE;
612 goto done;
615 for (;;)
617 if ((result = read( unix_handle, (char *)buffer + total, length - total )) >= 0)
619 total += result;
620 if (!result || total == length)
622 if (total)
624 status = STATUS_SUCCESS;
625 goto done;
627 switch (type)
629 case FD_TYPE_FILE:
630 case FD_TYPE_CHAR:
631 status = STATUS_END_OF_FILE;
632 goto done;
633 case FD_TYPE_SERIAL:
634 break;
635 default:
636 status = STATUS_PIPE_BROKEN;
637 goto done;
640 else if (type == FD_TYPE_FILE) continue; /* no async I/O on regular files */
642 else if (errno != EAGAIN)
644 if (errno == EINTR) continue;
645 if (!total) status = FILE_GetNtStatus();
646 goto done;
649 if (!(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)))
651 async_fileio_read *fileio;
652 BOOL avail_mode;
654 if ((status = get_io_avail_mode( hFile, type, &avail_mode )))
655 goto err;
656 if (total && avail_mode)
658 status = STATUS_SUCCESS;
659 goto done;
662 if (!(fileio = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(*fileio))))
664 status = STATUS_NO_MEMORY;
665 goto err;
667 fileio->io.handle = hFile;
668 fileio->io.apc = apc;
669 fileio->io.apc_arg = apc_user;
670 fileio->already = total;
671 fileio->count = length;
672 fileio->buffer = buffer;
673 fileio->avail_mode = avail_mode;
675 SERVER_START_REQ( register_async )
677 req->type = ASYNC_TYPE_READ;
678 req->count = length;
679 req->async.handle = wine_server_obj_handle( hFile );
680 req->async.event = wine_server_obj_handle( hEvent );
681 req->async.callback = wine_server_client_ptr( FILE_AsyncReadService );
682 req->async.iosb = wine_server_client_ptr( io_status );
683 req->async.arg = wine_server_client_ptr( fileio );
684 req->async.cvalue = cvalue;
685 status = wine_server_call( req );
687 SERVER_END_REQ;
689 if (status != STATUS_PENDING) RtlFreeHeap( GetProcessHeap(), 0, fileio );
690 goto err;
692 else /* synchronous read, wait for the fd to become ready */
694 struct pollfd pfd;
695 int ret, timeout;
697 if (!timeout_init_done)
699 timeout_init_done = 1;
700 if ((status = get_io_timeouts( hFile, type, length, TRUE, &timeouts )))
701 goto err;
702 if (hEvent) NtResetEvent( hEvent, NULL );
704 timeout = get_next_io_timeout( &timeouts, total );
706 pfd.fd = unix_handle;
707 pfd.events = POLLIN;
709 if (!timeout || !(ret = poll( &pfd, 1, timeout )))
711 if (total) /* return with what we got so far */
712 status = STATUS_SUCCESS;
713 else
714 status = (type == FD_TYPE_MAILSLOT) ? STATUS_IO_TIMEOUT : STATUS_TIMEOUT;
715 goto done;
717 if (ret == -1 && errno != EINTR)
719 status = FILE_GetNtStatus();
720 goto done;
722 /* will now restart the read */
726 done:
727 if (cvalue) NTDLL_AddCompletion( hFile, cvalue, status, total );
729 err:
730 if (needs_close) close( unix_handle );
731 if (status == STATUS_SUCCESS)
733 io_status->u.Status = status;
734 io_status->Information = total;
735 TRACE("= SUCCESS (%u)\n", total);
736 if (hEvent) NtSetEvent( hEvent, NULL );
737 if (apc) NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)apc,
738 (ULONG_PTR)apc_user, (ULONG_PTR)io_status, 0 );
740 else
742 TRACE("= 0x%08x\n", status);
743 if (status != STATUS_PENDING && hEvent) NtResetEvent( hEvent, NULL );
745 return status;
749 /******************************************************************************
750 * NtReadFileScatter [NTDLL.@]
751 * ZwReadFileScatter [NTDLL.@]
753 NTSTATUS WINAPI NtReadFileScatter( HANDLE file, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user,
754 PIO_STATUS_BLOCK io_status, FILE_SEGMENT_ELEMENT *segments,
755 ULONG length, PLARGE_INTEGER offset, PULONG key )
757 size_t page_size = getpagesize();
758 int result, unix_handle, needs_close;
759 unsigned int options;
760 NTSTATUS status;
761 ULONG pos = 0, total = 0;
762 enum server_fd_type type;
763 ULONG_PTR cvalue = apc ? 0 : (ULONG_PTR)apc_user;
765 TRACE( "(%p,%p,%p,%p,%p,%p,0x%08x,%p,%p),partial stub!\n",
766 file, event, apc, apc_user, io_status, segments, length, offset, key);
768 if (length % page_size) return STATUS_INVALID_PARAMETER;
769 if (!io_status) return STATUS_ACCESS_VIOLATION;
771 status = server_get_unix_fd( file, FILE_READ_DATA, &unix_handle,
772 &needs_close, &type, &options );
773 if (status) return status;
775 if ((type != FD_TYPE_FILE) ||
776 (options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)) ||
777 !(options & FILE_NO_INTERMEDIATE_BUFFERING))
779 status = STATUS_INVALID_PARAMETER;
780 goto error;
783 while (length)
785 if (offset && offset->QuadPart != (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */)
786 result = pread( unix_handle, (char *)segments->Buffer + pos,
787 page_size - pos, offset->QuadPart + total );
788 else
789 result = read( unix_handle, (char *)segments->Buffer + pos, page_size - pos );
791 if (result == -1)
793 if (errno == EINTR) continue;
794 status = FILE_GetNtStatus();
795 break;
797 if (!result)
799 status = STATUS_END_OF_FILE;
800 break;
802 total += result;
803 length -= result;
804 if ((pos += result) == page_size)
806 pos = 0;
807 segments++;
811 if (cvalue) NTDLL_AddCompletion( file, cvalue, status, total );
813 error:
814 if (needs_close) close( unix_handle );
815 if (status == STATUS_SUCCESS)
817 io_status->u.Status = status;
818 io_status->Information = total;
819 TRACE("= SUCCESS (%u)\n", total);
820 if (event) NtSetEvent( event, NULL );
821 if (apc) NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)apc,
822 (ULONG_PTR)apc_user, (ULONG_PTR)io_status, 0 );
824 else
826 TRACE("= 0x%08x\n", status);
827 if (status != STATUS_PENDING && event) NtResetEvent( event, NULL );
829 return status;
833 /***********************************************************************
834 * FILE_AsyncWriteService (INTERNAL)
836 static NTSTATUS FILE_AsyncWriteService(void *user, IO_STATUS_BLOCK *iosb, NTSTATUS status, void **apc)
838 async_fileio_write *fileio = user;
839 int result, fd, needs_close;
840 enum server_fd_type type;
842 switch (status)
844 case STATUS_ALERTED:
845 /* write some data (non-blocking) */
846 if ((status = server_get_unix_fd( fileio->io.handle, FILE_WRITE_DATA, &fd,
847 &needs_close, &type, NULL )))
848 break;
850 if (!fileio->count && (type == FD_TYPE_MAILSLOT || type == FD_TYPE_PIPE || type == FD_TYPE_SOCKET))
851 result = send( fd, fileio->buffer, 0, 0 );
852 else
853 result = write( fd, &fileio->buffer[fileio->already], fileio->count - fileio->already );
855 if (needs_close) close( fd );
857 if (result < 0)
859 if (errno == EAGAIN || errno == EINTR) status = STATUS_PENDING;
860 else status = FILE_GetNtStatus();
862 else
864 fileio->already += result;
865 status = (fileio->already < fileio->count) ? STATUS_PENDING : STATUS_SUCCESS;
867 break;
869 case STATUS_TIMEOUT:
870 case STATUS_IO_TIMEOUT:
871 if (fileio->already) status = STATUS_SUCCESS;
872 break;
874 if (status != STATUS_PENDING)
876 iosb->u.Status = status;
877 iosb->Information = fileio->already;
878 *apc = fileio_apc;
880 return status;
883 /******************************************************************************
884 * NtWriteFile [NTDLL.@]
885 * ZwWriteFile [NTDLL.@]
887 * Write to an open file handle.
889 * PARAMS
890 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
891 * Event [I] Event to signal upon completion (or NULL)
892 * ApcRoutine [I] Callback to call upon completion (or NULL)
893 * ApcContext [I] Context for ApcRoutine (or NULL)
894 * IoStatusBlock [O] Receives information about the operation on return
895 * Buffer [I] Source for the data to write
896 * Length [I] Size of Buffer
897 * ByteOffset [O] Destination for the new file pointer position (or NULL)
898 * Key [O] Function unknown (may be NULL)
900 * RETURNS
901 * Success: 0. IoStatusBlock is updated, and the Information member contains
902 * The number of bytes written.
903 * Failure: An NTSTATUS error code describing the error.
905 NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
906 PIO_APC_ROUTINE apc, void* apc_user,
907 PIO_STATUS_BLOCK io_status,
908 const void* buffer, ULONG length,
909 PLARGE_INTEGER offset, PULONG key)
911 int result, unix_handle, needs_close, timeout_init_done = 0;
912 unsigned int options;
913 struct io_timeouts timeouts;
914 NTSTATUS status;
915 ULONG total = 0;
916 enum server_fd_type type;
917 ULONG_PTR cvalue = apc ? 0 : (ULONG_PTR)apc_user;
919 TRACE("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%p)!\n",
920 hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
922 if (!io_status) return STATUS_ACCESS_VIOLATION;
924 status = server_get_unix_fd( hFile, FILE_WRITE_DATA, &unix_handle,
925 &needs_close, &type, &options );
926 if (status) return status;
928 if (!virtual_check_buffer_for_read( buffer, length ))
930 status = STATUS_INVALID_USER_BUFFER;
931 goto done;
934 if (type == FD_TYPE_FILE && offset && offset->QuadPart != (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */ )
936 /* async I/O doesn't make sense on regular files */
937 while ((result = pwrite( unix_handle, buffer, length, offset->QuadPart )) == -1)
939 if (errno != EINTR)
941 if (errno == EFAULT) status = STATUS_INVALID_USER_BUFFER;
942 else status = FILE_GetNtStatus();
943 goto done;
947 if (options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT))
948 /* update file pointer position */
949 lseek( unix_handle, offset->QuadPart + result, SEEK_SET );
951 total = result;
952 status = STATUS_SUCCESS;
953 goto done;
956 for (;;)
958 /* zero-length writes on sockets may not work with plain write(2) */
959 if (!length && (type == FD_TYPE_MAILSLOT || type == FD_TYPE_PIPE || type == FD_TYPE_SOCKET))
960 result = send( unix_handle, buffer, 0, 0 );
961 else
962 result = write( unix_handle, (const char *)buffer + total, length - total );
964 if (result >= 0)
966 total += result;
967 if (total == length)
969 status = STATUS_SUCCESS;
970 goto done;
972 if (type == FD_TYPE_FILE) continue; /* no async I/O on regular files */
974 else if (errno != EAGAIN)
976 if (errno == EINTR) continue;
977 if (!total)
979 if (errno == EFAULT) status = STATUS_INVALID_USER_BUFFER;
980 else status = FILE_GetNtStatus();
982 goto done;
985 if (!(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)))
987 async_fileio_write *fileio;
989 if (!(fileio = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(*fileio))))
991 status = STATUS_NO_MEMORY;
992 goto err;
994 fileio->io.handle = hFile;
995 fileio->io.apc = apc;
996 fileio->io.apc_arg = apc_user;
997 fileio->already = total;
998 fileio->count = length;
999 fileio->buffer = buffer;
1001 SERVER_START_REQ( register_async )
1003 req->type = ASYNC_TYPE_WRITE;
1004 req->count = length;
1005 req->async.handle = wine_server_obj_handle( hFile );
1006 req->async.event = wine_server_obj_handle( hEvent );
1007 req->async.callback = wine_server_client_ptr( FILE_AsyncWriteService );
1008 req->async.iosb = wine_server_client_ptr( io_status );
1009 req->async.arg = wine_server_client_ptr( fileio );
1010 req->async.cvalue = cvalue;
1011 status = wine_server_call( req );
1013 SERVER_END_REQ;
1015 if (status != STATUS_PENDING) RtlFreeHeap( GetProcessHeap(), 0, fileio );
1016 goto err;
1018 else /* synchronous write, wait for the fd to become ready */
1020 struct pollfd pfd;
1021 int ret, timeout;
1023 if (!timeout_init_done)
1025 timeout_init_done = 1;
1026 if ((status = get_io_timeouts( hFile, type, length, FALSE, &timeouts )))
1027 goto err;
1028 if (hEvent) NtResetEvent( hEvent, NULL );
1030 timeout = get_next_io_timeout( &timeouts, total );
1032 pfd.fd = unix_handle;
1033 pfd.events = POLLOUT;
1035 if (!timeout || !(ret = poll( &pfd, 1, timeout )))
1037 /* return with what we got so far */
1038 status = total ? STATUS_SUCCESS : STATUS_TIMEOUT;
1039 goto done;
1041 if (ret == -1 && errno != EINTR)
1043 status = FILE_GetNtStatus();
1044 goto done;
1046 /* will now restart the write */
1050 done:
1051 if (cvalue) NTDLL_AddCompletion( hFile, cvalue, status, total );
1053 err:
1054 if (needs_close) close( unix_handle );
1055 if (status == STATUS_SUCCESS)
1057 io_status->u.Status = status;
1058 io_status->Information = total;
1059 TRACE("= SUCCESS (%u)\n", total);
1060 if (hEvent) NtSetEvent( hEvent, NULL );
1061 if (apc) NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)apc,
1062 (ULONG_PTR)apc_user, (ULONG_PTR)io_status, 0 );
1064 else
1066 TRACE("= 0x%08x\n", status);
1067 if (status != STATUS_PENDING && hEvent) NtResetEvent( hEvent, NULL );
1069 return status;
1073 /******************************************************************************
1074 * NtWriteFileGather [NTDLL.@]
1075 * ZwWriteFileGather [NTDLL.@]
1077 NTSTATUS WINAPI NtWriteFileGather( HANDLE file, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user,
1078 PIO_STATUS_BLOCK io_status, FILE_SEGMENT_ELEMENT *segments,
1079 ULONG length, PLARGE_INTEGER offset, PULONG key )
1081 size_t page_size = getpagesize();
1082 int result, unix_handle, needs_close;
1083 unsigned int options;
1084 NTSTATUS status;
1085 ULONG pos = 0, total = 0;
1086 enum server_fd_type type;
1087 ULONG_PTR cvalue = apc ? 0 : (ULONG_PTR)apc_user;
1089 TRACE( "(%p,%p,%p,%p,%p,%p,0x%08x,%p,%p),partial stub!\n",
1090 file, event, apc, apc_user, io_status, segments, length, offset, key);
1092 if (length % page_size) return STATUS_INVALID_PARAMETER;
1093 if (!io_status) return STATUS_ACCESS_VIOLATION;
1095 status = server_get_unix_fd( file, FILE_WRITE_DATA, &unix_handle,
1096 &needs_close, &type, &options );
1097 if (status) return status;
1099 if ((type != FD_TYPE_FILE) ||
1100 (options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)) ||
1101 !(options & FILE_NO_INTERMEDIATE_BUFFERING))
1103 status = STATUS_INVALID_PARAMETER;
1104 goto error;
1107 while (length)
1109 if (offset && offset->QuadPart != (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */)
1110 result = pwrite( unix_handle, (char *)segments->Buffer + pos,
1111 page_size - pos, offset->QuadPart + total );
1112 else
1113 result = write( unix_handle, (char *)segments->Buffer + pos, page_size - pos );
1115 if (result == -1)
1117 if (errno == EINTR) continue;
1118 if (errno == EFAULT)
1120 status = STATUS_INVALID_USER_BUFFER;
1121 goto error;
1123 status = FILE_GetNtStatus();
1124 break;
1126 if (!result)
1128 status = STATUS_DISK_FULL;
1129 break;
1131 total += result;
1132 length -= result;
1133 if ((pos += result) == page_size)
1135 pos = 0;
1136 segments++;
1140 if (cvalue) NTDLL_AddCompletion( file, cvalue, status, total );
1142 error:
1143 if (needs_close) close( unix_handle );
1144 if (status == STATUS_SUCCESS)
1146 io_status->u.Status = status;
1147 io_status->Information = total;
1148 TRACE("= SUCCESS (%u)\n", total);
1149 if (event) NtSetEvent( event, NULL );
1150 if (apc) NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)apc,
1151 (ULONG_PTR)apc_user, (ULONG_PTR)io_status, 0 );
1153 else
1155 TRACE("= 0x%08x\n", status);
1156 if (status != STATUS_PENDING && event) NtResetEvent( event, NULL );
1158 return status;
1162 struct async_ioctl
1164 HANDLE handle; /* handle to the device */
1165 HANDLE event; /* async event */
1166 void *buffer; /* buffer for output */
1167 ULONG size; /* size of buffer */
1168 PIO_APC_ROUTINE apc; /* user apc params */
1169 void *apc_arg;
1172 /* callback for ioctl user APC */
1173 static void WINAPI ioctl_apc( void *arg, IO_STATUS_BLOCK *io, ULONG reserved )
1175 struct async_ioctl *async = arg;
1176 if (async->apc) async->apc( async->apc_arg, io, reserved );
1177 RtlFreeHeap( GetProcessHeap(), 0, async );
1180 /* callback for ioctl async I/O completion */
1181 static NTSTATUS ioctl_completion( void *arg, IO_STATUS_BLOCK *io, NTSTATUS status, void **apc )
1183 struct async_ioctl *async = arg;
1185 if (status == STATUS_ALERTED)
1187 SERVER_START_REQ( get_ioctl_result )
1189 req->handle = wine_server_obj_handle( async->handle );
1190 req->user_arg = wine_server_client_ptr( async );
1191 wine_server_set_reply( req, async->buffer, async->size );
1192 status = wine_server_call( req );
1193 if (status != STATUS_PENDING) io->Information = wine_server_reply_size( reply );
1195 SERVER_END_REQ;
1197 if (status != STATUS_PENDING)
1199 io->u.Status = status;
1200 if (async->apc || async->event) *apc = ioctl_apc;
1202 return status;
1205 /* do a ioctl call through the server */
1206 static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event,
1207 PIO_APC_ROUTINE apc, PVOID apc_context,
1208 IO_STATUS_BLOCK *io, ULONG code,
1209 const void *in_buffer, ULONG in_size,
1210 PVOID out_buffer, ULONG out_size )
1212 struct async_ioctl *async;
1213 NTSTATUS status;
1214 HANDLE wait_handle;
1215 ULONG options;
1216 ULONG_PTR cvalue = apc ? 0 : (ULONG_PTR)apc_context;
1218 if (!(async = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*async) )))
1219 return STATUS_NO_MEMORY;
1220 async->handle = handle;
1221 async->event = event;
1222 async->buffer = out_buffer;
1223 async->size = out_size;
1224 async->apc = apc;
1225 async->apc_arg = apc_context;
1227 SERVER_START_REQ( ioctl )
1229 req->code = code;
1230 req->blocking = !apc && !event;
1231 req->async.handle = wine_server_obj_handle( handle );
1232 req->async.callback = wine_server_client_ptr( ioctl_completion );
1233 req->async.iosb = wine_server_client_ptr( io );
1234 req->async.arg = wine_server_client_ptr( async );
1235 req->async.event = wine_server_obj_handle( event );
1236 req->async.cvalue = cvalue;
1237 wine_server_add_data( req, in_buffer, in_size );
1238 wine_server_set_reply( req, out_buffer, out_size );
1239 status = wine_server_call( req );
1240 wait_handle = wine_server_ptr_handle( reply->wait );
1241 options = reply->options;
1242 if (status != STATUS_PENDING) io->Information = wine_server_reply_size( reply );
1244 SERVER_END_REQ;
1246 if (status == STATUS_NOT_SUPPORTED)
1247 FIXME("Unsupported ioctl %x (device=%x access=%x func=%x method=%x)\n",
1248 code, code >> 16, (code >> 14) & 3, (code >> 2) & 0xfff, code & 3);
1250 if (status != STATUS_PENDING) RtlFreeHeap( GetProcessHeap(), 0, async );
1252 if (wait_handle)
1254 NtWaitForSingleObject( wait_handle, (options & FILE_SYNCHRONOUS_IO_ALERT), NULL );
1255 status = io->u.Status;
1256 NtClose( wait_handle );
1257 RtlFreeHeap( GetProcessHeap(), 0, async );
1260 return status;
1263 /* Tell Valgrind to ignore any holes in structs we will be passing to the
1264 * server */
1265 static void ignore_server_ioctl_struct_holes (ULONG code, const void *in_buffer,
1266 ULONG in_size)
1268 #ifdef VALGRIND_MAKE_MEM_DEFINED
1269 # define IGNORE_STRUCT_HOLE(buf, size, t, f1, f2) \
1270 do { \
1271 if ((size) >= FIELD_OFFSET(t, f2) && \
1272 FIELD_OFFSET(t, f1) + sizeof(((t *)0)->f1) < FIELD_OFFSET(t, f2)) \
1273 VALGRIND_MAKE_MEM_DEFINED( \
1274 (const char *)(buf) + FIELD_OFFSET(t, f1) + sizeof(((t *)0)->f1), \
1275 FIELD_OFFSET(t, f2) - FIELD_OFFSET(t, f1) + sizeof(((t *)0)->f1)); \
1276 } while (0)
1278 switch (code)
1280 case FSCTL_PIPE_WAIT:
1281 IGNORE_STRUCT_HOLE(in_buffer, in_size, FILE_PIPE_WAIT_FOR_BUFFER, TimeoutSpecified, Name);
1282 break;
1284 #endif
1288 /**************************************************************************
1289 * NtDeviceIoControlFile [NTDLL.@]
1290 * ZwDeviceIoControlFile [NTDLL.@]
1292 * Perform an I/O control operation on an open file handle.
1294 * PARAMS
1295 * handle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
1296 * event [I] Event to signal upon completion (or NULL)
1297 * apc [I] Callback to call upon completion (or NULL)
1298 * apc_context [I] Context for ApcRoutine (or NULL)
1299 * io [O] Receives information about the operation on return
1300 * code [I] Control code for the operation to perform
1301 * in_buffer [I] Source for any input data required (or NULL)
1302 * in_size [I] Size of InputBuffer
1303 * out_buffer [O] Source for any output data returned (or NULL)
1304 * out_size [I] Size of OutputBuffer
1306 * RETURNS
1307 * Success: 0. IoStatusBlock is updated.
1308 * Failure: An NTSTATUS error code describing the error.
1310 NTSTATUS WINAPI NtDeviceIoControlFile(HANDLE handle, HANDLE event,
1311 PIO_APC_ROUTINE apc, PVOID apc_context,
1312 PIO_STATUS_BLOCK io, ULONG code,
1313 PVOID in_buffer, ULONG in_size,
1314 PVOID out_buffer, ULONG out_size)
1316 ULONG device = (code >> 16);
1317 NTSTATUS status = STATUS_NOT_SUPPORTED;
1319 TRACE("(%p,%p,%p,%p,%p,0x%08x,%p,0x%08x,%p,0x%08x)\n",
1320 handle, event, apc, apc_context, io, code,
1321 in_buffer, in_size, out_buffer, out_size);
1323 switch(device)
1325 case FILE_DEVICE_DISK:
1326 case FILE_DEVICE_CD_ROM:
1327 case FILE_DEVICE_DVD:
1328 case FILE_DEVICE_CONTROLLER:
1329 case FILE_DEVICE_MASS_STORAGE:
1330 status = CDROM_DeviceIoControl(handle, event, apc, apc_context, io, code,
1331 in_buffer, in_size, out_buffer, out_size);
1332 break;
1333 case FILE_DEVICE_SERIAL_PORT:
1334 status = COMM_DeviceIoControl(handle, event, apc, apc_context, io, code,
1335 in_buffer, in_size, out_buffer, out_size);
1336 break;
1337 case FILE_DEVICE_TAPE:
1338 status = TAPE_DeviceIoControl(handle, event, apc, apc_context, io, code,
1339 in_buffer, in_size, out_buffer, out_size);
1340 break;
1343 if (status == STATUS_NOT_SUPPORTED || status == STATUS_BAD_DEVICE_TYPE)
1344 status = server_ioctl_file( handle, event, apc, apc_context, io, code,
1345 in_buffer, in_size, out_buffer, out_size );
1347 if (status != STATUS_PENDING) io->u.Status = status;
1348 return status;
1352 /**************************************************************************
1353 * NtFsControlFile [NTDLL.@]
1354 * ZwFsControlFile [NTDLL.@]
1356 * Perform a file system control operation on an open file handle.
1358 * PARAMS
1359 * handle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
1360 * event [I] Event to signal upon completion (or NULL)
1361 * apc [I] Callback to call upon completion (or NULL)
1362 * apc_context [I] Context for ApcRoutine (or NULL)
1363 * io [O] Receives information about the operation on return
1364 * code [I] Control code for the operation to perform
1365 * in_buffer [I] Source for any input data required (or NULL)
1366 * in_size [I] Size of InputBuffer
1367 * out_buffer [O] Source for any output data returned (or NULL)
1368 * out_size [I] Size of OutputBuffer
1370 * RETURNS
1371 * Success: 0. IoStatusBlock is updated.
1372 * Failure: An NTSTATUS error code describing the error.
1374 NTSTATUS WINAPI NtFsControlFile(HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc,
1375 PVOID apc_context, PIO_STATUS_BLOCK io, ULONG code,
1376 PVOID in_buffer, ULONG in_size, PVOID out_buffer, ULONG out_size)
1378 NTSTATUS status;
1380 TRACE("(%p,%p,%p,%p,%p,0x%08x,%p,0x%08x,%p,0x%08x)\n",
1381 handle, event, apc, apc_context, io, code,
1382 in_buffer, in_size, out_buffer, out_size);
1384 if (!io) return STATUS_INVALID_PARAMETER;
1386 ignore_server_ioctl_struct_holes( code, in_buffer, in_size );
1388 switch(code)
1390 case FSCTL_DISMOUNT_VOLUME:
1391 status = server_ioctl_file( handle, event, apc, apc_context, io, code,
1392 in_buffer, in_size, out_buffer, out_size );
1393 if (!status) status = DIR_unmount_device( handle );
1394 break;
1396 case FSCTL_PIPE_PEEK:
1398 FILE_PIPE_PEEK_BUFFER *buffer = out_buffer;
1399 int avail = 0, fd, needs_close;
1401 if (out_size < FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data ))
1403 status = STATUS_INFO_LENGTH_MISMATCH;
1404 break;
1407 if ((status = server_get_unix_fd( handle, FILE_READ_DATA, &fd, &needs_close, NULL, NULL )))
1408 break;
1410 #ifdef FIONREAD
1411 if (ioctl( fd, FIONREAD, &avail ) != 0)
1413 TRACE("FIONREAD failed reason: %s\n",strerror(errno));
1414 if (needs_close) close( fd );
1415 status = FILE_GetNtStatus();
1416 break;
1418 #endif
1419 if (!avail) /* check for closed pipe */
1421 struct pollfd pollfd;
1422 int ret;
1424 pollfd.fd = fd;
1425 pollfd.events = POLLIN;
1426 pollfd.revents = 0;
1427 ret = poll( &pollfd, 1, 0 );
1428 if (ret == -1 || (ret == 1 && (pollfd.revents & (POLLHUP|POLLERR))))
1430 if (needs_close) close( fd );
1431 status = STATUS_PIPE_BROKEN;
1432 break;
1435 buffer->NamedPipeState = 0; /* FIXME */
1436 buffer->ReadDataAvailable = avail;
1437 buffer->NumberOfMessages = 0; /* FIXME */
1438 buffer->MessageLength = 0; /* FIXME */
1439 io->Information = FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data );
1440 status = STATUS_SUCCESS;
1441 if (avail)
1443 ULONG data_size = out_size - FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data );
1444 if (data_size)
1446 int res = recv( fd, buffer->Data, data_size, MSG_PEEK );
1447 if (res >= 0) io->Information += res;
1450 if (needs_close) close( fd );
1452 break;
1454 case FSCTL_PIPE_DISCONNECT:
1455 status = server_ioctl_file( handle, event, apc, apc_context, io, code,
1456 in_buffer, in_size, out_buffer, out_size );
1457 if (!status)
1459 int fd = server_remove_fd_from_cache( handle );
1460 if (fd != -1) close( fd );
1462 break;
1464 case FSCTL_PIPE_IMPERSONATE:
1465 FIXME("FSCTL_PIPE_IMPERSONATE: impersonating self\n");
1466 status = RtlImpersonateSelf( SecurityImpersonation );
1467 break;
1469 case FSCTL_LOCK_VOLUME:
1470 case FSCTL_UNLOCK_VOLUME:
1471 FIXME("stub! return success - Unsupported fsctl %x (device=%x access=%x func=%x method=%x)\n",
1472 code, code >> 16, (code >> 14) & 3, (code >> 2) & 0xfff, code & 3);
1473 status = STATUS_SUCCESS;
1474 break;
1476 case FSCTL_PIPE_LISTEN:
1477 case FSCTL_PIPE_WAIT:
1478 default:
1479 status = server_ioctl_file( handle, event, apc, apc_context, io, code,
1480 in_buffer, in_size, out_buffer, out_size );
1481 break;
1484 if (status != STATUS_PENDING) io->u.Status = status;
1485 return status;
1488 /******************************************************************************
1489 * NtSetVolumeInformationFile [NTDLL.@]
1490 * ZwSetVolumeInformationFile [NTDLL.@]
1492 * Set volume information for an open file handle.
1494 * PARAMS
1495 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
1496 * IoStatusBlock [O] Receives information about the operation on return
1497 * FsInformation [I] Source for volume information
1498 * Length [I] Size of FsInformation
1499 * FsInformationClass [I] Type of volume information to set
1501 * RETURNS
1502 * Success: 0. IoStatusBlock is updated.
1503 * Failure: An NTSTATUS error code describing the error.
1505 NTSTATUS WINAPI NtSetVolumeInformationFile(
1506 IN HANDLE FileHandle,
1507 PIO_STATUS_BLOCK IoStatusBlock,
1508 PVOID FsInformation,
1509 ULONG Length,
1510 FS_INFORMATION_CLASS FsInformationClass)
1512 FIXME("(%p,%p,%p,0x%08x,0x%08x) stub\n",
1513 FileHandle,IoStatusBlock,FsInformation,Length,FsInformationClass);
1514 return 0;
1517 static inline void get_file_times( const struct stat *st, LARGE_INTEGER *mtime, LARGE_INTEGER *ctime,
1518 LARGE_INTEGER *atime, LARGE_INTEGER *creation )
1520 RtlSecondsSince1970ToTime( st->st_mtime, mtime );
1521 RtlSecondsSince1970ToTime( st->st_ctime, ctime );
1522 RtlSecondsSince1970ToTime( st->st_atime, atime );
1523 #ifdef HAVE_STRUCT_STAT_ST_MTIM
1524 mtime->QuadPart += st->st_mtim.tv_nsec / 100;
1525 #endif
1526 #ifdef HAVE_STRUCT_STAT_ST_CTIM
1527 ctime->QuadPart += st->st_ctim.tv_nsec / 100;
1528 #endif
1529 #ifdef HAVE_STRUCT_STAT_ST_ATIM
1530 atime->QuadPart += st->st_atim.tv_nsec / 100;
1531 #endif
1532 *creation = *mtime;
1535 /* fill in the file information that depends on the stat info */
1536 NTSTATUS fill_stat_info( const struct stat *st, void *ptr, FILE_INFORMATION_CLASS class )
1538 switch (class)
1540 case FileBasicInformation:
1542 FILE_BASIC_INFORMATION *info = ptr;
1544 get_file_times( st, &info->LastWriteTime, &info->ChangeTime,
1545 &info->LastAccessTime, &info->CreationTime );
1546 if (S_ISDIR(st->st_mode)) info->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
1547 else info->FileAttributes = FILE_ATTRIBUTE_ARCHIVE;
1548 if (!(st->st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
1549 info->FileAttributes |= FILE_ATTRIBUTE_READONLY;
1551 break;
1552 case FileStandardInformation:
1554 FILE_STANDARD_INFORMATION *info = ptr;
1556 if ((info->Directory = S_ISDIR(st->st_mode)))
1558 info->AllocationSize.QuadPart = 0;
1559 info->EndOfFile.QuadPart = 0;
1560 info->NumberOfLinks = 1;
1562 else
1564 info->AllocationSize.QuadPart = (ULONGLONG)st->st_blocks * 512;
1565 info->EndOfFile.QuadPart = st->st_size;
1566 info->NumberOfLinks = st->st_nlink;
1569 break;
1570 case FileInternalInformation:
1572 FILE_INTERNAL_INFORMATION *info = ptr;
1573 info->IndexNumber.QuadPart = st->st_ino;
1575 break;
1576 case FileEndOfFileInformation:
1578 FILE_END_OF_FILE_INFORMATION *info = ptr;
1579 info->EndOfFile.QuadPart = S_ISDIR(st->st_mode) ? 0 : st->st_size;
1581 break;
1582 case FileAllInformation:
1584 FILE_ALL_INFORMATION *info = ptr;
1585 fill_stat_info( st, &info->BasicInformation, FileBasicInformation );
1586 fill_stat_info( st, &info->StandardInformation, FileStandardInformation );
1587 fill_stat_info( st, &info->InternalInformation, FileInternalInformation );
1589 break;
1590 /* all directory structures start with the FileDirectoryInformation layout */
1591 case FileBothDirectoryInformation:
1592 case FileFullDirectoryInformation:
1593 case FileDirectoryInformation:
1595 FILE_DIRECTORY_INFORMATION *info = ptr;
1597 get_file_times( st, &info->LastWriteTime, &info->ChangeTime,
1598 &info->LastAccessTime, &info->CreationTime );
1599 if (S_ISDIR(st->st_mode))
1601 info->AllocationSize.QuadPart = 0;
1602 info->EndOfFile.QuadPart = 0;
1603 info->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
1605 else
1607 info->AllocationSize.QuadPart = (ULONGLONG)st->st_blocks * 512;
1608 info->EndOfFile.QuadPart = st->st_size;
1609 info->FileAttributes = FILE_ATTRIBUTE_ARCHIVE;
1611 if (!(st->st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
1612 info->FileAttributes |= FILE_ATTRIBUTE_READONLY;
1614 break;
1615 case FileIdFullDirectoryInformation:
1617 FILE_ID_FULL_DIRECTORY_INFORMATION *info = ptr;
1618 info->FileId.QuadPart = st->st_ino;
1619 fill_stat_info( st, info, FileDirectoryInformation );
1621 break;
1622 case FileIdBothDirectoryInformation:
1624 FILE_ID_BOTH_DIRECTORY_INFORMATION *info = ptr;
1625 info->FileId.QuadPart = st->st_ino;
1626 fill_stat_info( st, info, FileDirectoryInformation );
1628 break;
1630 default:
1631 return STATUS_INVALID_INFO_CLASS;
1633 return STATUS_SUCCESS;
1636 NTSTATUS server_get_unix_name( HANDLE handle, ANSI_STRING *unix_name )
1638 data_size_t size = 1024;
1639 NTSTATUS ret;
1640 char *name;
1642 for (;;)
1644 name = RtlAllocateHeap( GetProcessHeap(), 0, size + 1 );
1645 if (!name) return STATUS_NO_MEMORY;
1646 unix_name->MaximumLength = size + 1;
1648 SERVER_START_REQ( get_handle_unix_name )
1650 req->handle = wine_server_obj_handle( handle );
1651 wine_server_set_reply( req, name, size );
1652 ret = wine_server_call( req );
1653 size = reply->name_len;
1655 SERVER_END_REQ;
1657 if (!ret)
1659 name[size] = 0;
1660 unix_name->Buffer = name;
1661 unix_name->Length = size;
1662 break;
1664 RtlFreeHeap( GetProcessHeap(), 0, name );
1665 if (ret != STATUS_BUFFER_OVERFLOW) break;
1667 return ret;
1670 static NTSTATUS fill_name_info( const ANSI_STRING *unix_name, FILE_NAME_INFORMATION *info, LONG *name_len )
1672 UNICODE_STRING nt_name;
1673 NTSTATUS status;
1675 if (!(status = wine_unix_to_nt_file_name( unix_name, &nt_name )))
1677 const WCHAR *ptr = nt_name.Buffer;
1678 const WCHAR *end = ptr + (nt_name.Length / sizeof(WCHAR));
1680 /* Skip the volume mount point. */
1681 while (ptr != end && *ptr == '\\') ++ptr;
1682 while (ptr != end && *ptr != '\\') ++ptr;
1683 while (ptr != end && *ptr == '\\') ++ptr;
1684 while (ptr != end && *ptr != '\\') ++ptr;
1686 info->FileNameLength = (end - ptr) * sizeof(WCHAR);
1687 if (*name_len < info->FileNameLength) status = STATUS_BUFFER_OVERFLOW;
1688 else *name_len = info->FileNameLength;
1690 memcpy( info->FileName, ptr, *name_len );
1691 RtlFreeUnicodeString( &nt_name );
1694 return status;
1697 /******************************************************************************
1698 * NtQueryInformationFile [NTDLL.@]
1699 * ZwQueryInformationFile [NTDLL.@]
1701 * Get information about an open file handle.
1703 * PARAMS
1704 * hFile [I] Handle returned from ZwOpenFile() or ZwCreateFile()
1705 * io [O] Receives information about the operation on return
1706 * ptr [O] Destination for file information
1707 * len [I] Size of FileInformation
1708 * class [I] Type of file information to get
1710 * RETURNS
1711 * Success: 0. IoStatusBlock and FileInformation are updated.
1712 * Failure: An NTSTATUS error code describing the error.
1714 NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
1715 PVOID ptr, LONG len, FILE_INFORMATION_CLASS class )
1717 static const size_t info_sizes[] =
1720 sizeof(FILE_DIRECTORY_INFORMATION), /* FileDirectoryInformation */
1721 sizeof(FILE_FULL_DIRECTORY_INFORMATION), /* FileFullDirectoryInformation */
1722 sizeof(FILE_BOTH_DIRECTORY_INFORMATION), /* FileBothDirectoryInformation */
1723 sizeof(FILE_BASIC_INFORMATION), /* FileBasicInformation */
1724 sizeof(FILE_STANDARD_INFORMATION), /* FileStandardInformation */
1725 sizeof(FILE_INTERNAL_INFORMATION), /* FileInternalInformation */
1726 sizeof(FILE_EA_INFORMATION), /* FileEaInformation */
1727 sizeof(FILE_ACCESS_INFORMATION), /* FileAccessInformation */
1728 sizeof(FILE_NAME_INFORMATION), /* FileNameInformation */
1729 sizeof(FILE_RENAME_INFORMATION)-sizeof(WCHAR), /* FileRenameInformation */
1730 0, /* FileLinkInformation */
1731 sizeof(FILE_NAMES_INFORMATION)-sizeof(WCHAR), /* FileNamesInformation */
1732 sizeof(FILE_DISPOSITION_INFORMATION), /* FileDispositionInformation */
1733 sizeof(FILE_POSITION_INFORMATION), /* FilePositionInformation */
1734 sizeof(FILE_FULL_EA_INFORMATION), /* FileFullEaInformation */
1735 sizeof(FILE_MODE_INFORMATION), /* FileModeInformation */
1736 sizeof(FILE_ALIGNMENT_INFORMATION), /* FileAlignmentInformation */
1737 sizeof(FILE_ALL_INFORMATION), /* FileAllInformation */
1738 sizeof(FILE_ALLOCATION_INFORMATION), /* FileAllocationInformation */
1739 sizeof(FILE_END_OF_FILE_INFORMATION), /* FileEndOfFileInformation */
1740 0, /* FileAlternateNameInformation */
1741 sizeof(FILE_STREAM_INFORMATION)-sizeof(WCHAR), /* FileStreamInformation */
1742 0, /* FilePipeInformation */
1743 sizeof(FILE_PIPE_LOCAL_INFORMATION), /* FilePipeLocalInformation */
1744 0, /* FilePipeRemoteInformation */
1745 sizeof(FILE_MAILSLOT_QUERY_INFORMATION), /* FileMailslotQueryInformation */
1746 0, /* FileMailslotSetInformation */
1747 0, /* FileCompressionInformation */
1748 0, /* FileObjectIdInformation */
1749 0, /* FileCompletionInformation */
1750 0, /* FileMoveClusterInformation */
1751 0, /* FileQuotaInformation */
1752 0, /* FileReparsePointInformation */
1753 0, /* FileNetworkOpenInformation */
1754 0, /* FileAttributeTagInformation */
1755 0, /* FileTrackingInformation */
1756 0, /* FileIdBothDirectoryInformation */
1757 0, /* FileIdFullDirectoryInformation */
1758 0, /* FileValidDataLengthInformation */
1759 0, /* FileShortNameInformation */
1763 0, /* FileSfioReserveInformation */
1764 0, /* FileSfioVolumeInformation */
1765 0, /* FileHardLinkInformation */
1767 0, /* FileNormalizedNameInformation */
1769 0, /* FileIdGlobalTxDirectoryInformation */
1773 0 /* FileStandardLinkInformation */
1776 struct stat st;
1777 int fd, needs_close = FALSE;
1779 TRACE("(%p,%p,%p,0x%08x,0x%08x)\n", hFile, io, ptr, len, class);
1781 io->Information = 0;
1783 if (class <= 0 || class >= FileMaximumInformation)
1784 return io->u.Status = STATUS_INVALID_INFO_CLASS;
1785 if (!info_sizes[class])
1787 FIXME("Unsupported class (%d)\n", class);
1788 return io->u.Status = STATUS_NOT_IMPLEMENTED;
1790 if (len < info_sizes[class])
1791 return io->u.Status = STATUS_INFO_LENGTH_MISMATCH;
1793 if (class != FilePipeLocalInformation)
1795 if ((io->u.Status = server_get_unix_fd( hFile, 0, &fd, &needs_close, NULL, NULL )))
1796 return io->u.Status;
1799 switch (class)
1801 case FileBasicInformation:
1802 if (fstat( fd, &st ) == -1)
1803 io->u.Status = FILE_GetNtStatus();
1804 else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
1805 io->u.Status = STATUS_INVALID_INFO_CLASS;
1806 else
1807 fill_stat_info( &st, ptr, class );
1808 break;
1809 case FileStandardInformation:
1811 FILE_STANDARD_INFORMATION *info = ptr;
1813 if (fstat( fd, &st ) == -1) io->u.Status = FILE_GetNtStatus();
1814 else
1816 fill_stat_info( &st, info, class );
1817 info->DeletePending = FALSE; /* FIXME */
1820 break;
1821 case FilePositionInformation:
1823 FILE_POSITION_INFORMATION *info = ptr;
1824 off_t res = lseek( fd, 0, SEEK_CUR );
1825 if (res == (off_t)-1) io->u.Status = FILE_GetNtStatus();
1826 else info->CurrentByteOffset.QuadPart = res;
1828 break;
1829 case FileInternalInformation:
1830 if (fstat( fd, &st ) == -1) io->u.Status = FILE_GetNtStatus();
1831 else fill_stat_info( &st, ptr, class );
1832 break;
1833 case FileEaInformation:
1835 FILE_EA_INFORMATION *info = ptr;
1836 info->EaSize = 0;
1838 break;
1839 case FileEndOfFileInformation:
1840 if (fstat( fd, &st ) == -1) io->u.Status = FILE_GetNtStatus();
1841 else fill_stat_info( &st, ptr, class );
1842 break;
1843 case FileAllInformation:
1845 FILE_ALL_INFORMATION *info = ptr;
1846 ANSI_STRING unix_name;
1848 if (fstat( fd, &st ) == -1) io->u.Status = FILE_GetNtStatus();
1849 else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
1850 io->u.Status = STATUS_INVALID_INFO_CLASS;
1851 else if (!(io->u.Status = server_get_unix_name( hFile, &unix_name )))
1853 LONG name_len = len - FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName);
1855 fill_stat_info( &st, info, FileAllInformation );
1856 info->StandardInformation.DeletePending = FALSE; /* FIXME */
1857 info->EaInformation.EaSize = 0;
1858 info->AccessInformation.AccessFlags = 0; /* FIXME */
1859 info->PositionInformation.CurrentByteOffset.QuadPart = lseek( fd, 0, SEEK_CUR );
1860 info->ModeInformation.Mode = 0; /* FIXME */
1861 info->AlignmentInformation.AlignmentRequirement = 1; /* FIXME */
1863 io->u.Status = fill_name_info( &unix_name, &info->NameInformation, &name_len );
1864 RtlFreeAnsiString( &unix_name );
1865 io->Information = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + name_len;
1868 break;
1869 case FileMailslotQueryInformation:
1871 FILE_MAILSLOT_QUERY_INFORMATION *info = ptr;
1873 SERVER_START_REQ( set_mailslot_info )
1875 req->handle = wine_server_obj_handle( hFile );
1876 req->flags = 0;
1877 io->u.Status = wine_server_call( req );
1878 if( io->u.Status == STATUS_SUCCESS )
1880 info->MaximumMessageSize = reply->max_msgsize;
1881 info->MailslotQuota = 0;
1882 info->NextMessageSize = 0;
1883 info->MessagesAvailable = 0;
1884 info->ReadTimeout.QuadPart = reply->read_timeout;
1887 SERVER_END_REQ;
1888 if (!io->u.Status)
1890 char *tmpbuf;
1891 ULONG size = info->MaximumMessageSize ? info->MaximumMessageSize : 0x10000;
1892 if (size > 0x10000) size = 0x10000;
1893 if ((tmpbuf = RtlAllocateHeap( GetProcessHeap(), 0, size )))
1895 int fd, needs_close;
1896 if (!server_get_unix_fd( hFile, FILE_READ_DATA, &fd, &needs_close, NULL, NULL ))
1898 int res = recv( fd, tmpbuf, size, MSG_PEEK );
1899 info->MessagesAvailable = (res > 0);
1900 info->NextMessageSize = (res >= 0) ? res : MAILSLOT_NO_MESSAGE;
1901 if (needs_close) close( fd );
1903 RtlFreeHeap( GetProcessHeap(), 0, tmpbuf );
1907 break;
1908 case FilePipeLocalInformation:
1910 FILE_PIPE_LOCAL_INFORMATION* pli = ptr;
1912 SERVER_START_REQ( get_named_pipe_info )
1914 req->handle = wine_server_obj_handle( hFile );
1915 if (!(io->u.Status = wine_server_call( req )))
1917 pli->NamedPipeType = (reply->flags & NAMED_PIPE_MESSAGE_STREAM_WRITE) ?
1918 FILE_PIPE_TYPE_MESSAGE : FILE_PIPE_TYPE_BYTE;
1919 pli->NamedPipeConfiguration = 0; /* FIXME */
1920 pli->MaximumInstances = reply->maxinstances;
1921 pli->CurrentInstances = reply->instances;
1922 pli->InboundQuota = reply->insize;
1923 pli->ReadDataAvailable = 0; /* FIXME */
1924 pli->OutboundQuota = reply->outsize;
1925 pli->WriteQuotaAvailable = 0; /* FIXME */
1926 pli->NamedPipeState = 0; /* FIXME */
1927 pli->NamedPipeEnd = (reply->flags & NAMED_PIPE_SERVER_END) ?
1928 FILE_PIPE_SERVER_END : FILE_PIPE_CLIENT_END;
1931 SERVER_END_REQ;
1933 break;
1934 case FileNameInformation:
1936 FILE_NAME_INFORMATION *info = ptr;
1937 ANSI_STRING unix_name;
1939 if (!(io->u.Status = server_get_unix_name( hFile, &unix_name )))
1941 LONG name_len = len - FIELD_OFFSET(FILE_NAME_INFORMATION, FileName);
1942 io->u.Status = fill_name_info( &unix_name, info, &name_len );
1943 RtlFreeAnsiString( &unix_name );
1944 io->Information = FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + name_len;
1947 break;
1948 default:
1949 FIXME("Unsupported class (%d)\n", class);
1950 io->u.Status = STATUS_NOT_IMPLEMENTED;
1951 break;
1953 if (needs_close) close( fd );
1954 if (io->u.Status == STATUS_SUCCESS && !io->Information) io->Information = info_sizes[class];
1955 return io->u.Status;
1958 /******************************************************************************
1959 * NtSetInformationFile [NTDLL.@]
1960 * ZwSetInformationFile [NTDLL.@]
1962 * Set information about an open file handle.
1964 * PARAMS
1965 * handle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
1966 * io [O] Receives information about the operation on return
1967 * ptr [I] Source for file information
1968 * len [I] Size of FileInformation
1969 * class [I] Type of file information to set
1971 * RETURNS
1972 * Success: 0. io is updated.
1973 * Failure: An NTSTATUS error code describing the error.
1975 NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io,
1976 PVOID ptr, ULONG len, FILE_INFORMATION_CLASS class)
1978 int fd, needs_close;
1980 TRACE("(%p,%p,%p,0x%08x,0x%08x)\n", handle, io, ptr, len, class);
1982 io->u.Status = STATUS_SUCCESS;
1983 switch (class)
1985 case FileBasicInformation:
1986 if (len >= sizeof(FILE_BASIC_INFORMATION))
1988 struct stat st;
1989 const FILE_BASIC_INFORMATION *info = ptr;
1991 if ((io->u.Status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )))
1992 return io->u.Status;
1994 if (info->LastAccessTime.QuadPart || info->LastWriteTime.QuadPart)
1996 struct timeval tv[2];
1998 if (!info->LastAccessTime.QuadPart || !info->LastWriteTime.QuadPart)
2001 tv[0].tv_sec = tv[0].tv_usec = 0;
2002 tv[1].tv_sec = tv[1].tv_usec = 0;
2003 if (!fstat( fd, &st ))
2005 tv[0].tv_sec = st.st_atime;
2006 tv[1].tv_sec = st.st_mtime;
2009 if (info->LastAccessTime.QuadPart)
2011 ULONGLONG sec = info->LastAccessTime.QuadPart / 10000000;
2012 UINT nsec = info->LastAccessTime.QuadPart % 10000000;
2013 tv[0].tv_sec = sec - SECS_1601_TO_1970;
2014 tv[0].tv_usec = nsec / 10;
2016 if (info->LastWriteTime.QuadPart)
2018 ULONGLONG sec = info->LastWriteTime.QuadPart / 10000000;
2019 UINT nsec = info->LastWriteTime.QuadPart % 10000000;
2020 tv[1].tv_sec = sec - SECS_1601_TO_1970;
2021 tv[1].tv_usec = nsec / 10;
2023 if (futimes( fd, tv ) == -1) io->u.Status = FILE_GetNtStatus();
2026 if (io->u.Status == STATUS_SUCCESS && info->FileAttributes)
2028 if (fstat( fd, &st ) == -1) io->u.Status = FILE_GetNtStatus();
2029 else
2031 if (info->FileAttributes & FILE_ATTRIBUTE_READONLY)
2033 if (S_ISDIR( st.st_mode))
2034 WARN("FILE_ATTRIBUTE_READONLY ignored for directory.\n");
2035 else
2036 st.st_mode &= ~0222; /* clear write permission bits */
2038 else
2040 /* add write permission only where we already have read permission */
2041 st.st_mode |= (0600 | ((st.st_mode & 044) >> 1)) & (~FILE_umask);
2043 if (fchmod( fd, st.st_mode ) == -1) io->u.Status = FILE_GetNtStatus();
2047 if (needs_close) close( fd );
2049 else io->u.Status = STATUS_INVALID_PARAMETER_3;
2050 break;
2052 case FilePositionInformation:
2053 if (len >= sizeof(FILE_POSITION_INFORMATION))
2055 const FILE_POSITION_INFORMATION *info = ptr;
2057 if ((io->u.Status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )))
2058 return io->u.Status;
2060 if (lseek( fd, info->CurrentByteOffset.QuadPart, SEEK_SET ) == (off_t)-1)
2061 io->u.Status = FILE_GetNtStatus();
2063 if (needs_close) close( fd );
2065 else io->u.Status = STATUS_INVALID_PARAMETER_3;
2066 break;
2068 case FileEndOfFileInformation:
2069 if (len >= sizeof(FILE_END_OF_FILE_INFORMATION))
2071 struct stat st;
2072 const FILE_END_OF_FILE_INFORMATION *info = ptr;
2074 if ((io->u.Status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )))
2075 return io->u.Status;
2077 /* first try normal truncate */
2078 if (ftruncate( fd, (off_t)info->EndOfFile.QuadPart ) != -1) break;
2080 /* now check for the need to extend the file */
2081 if (fstat( fd, &st ) != -1 && (off_t)info->EndOfFile.QuadPart > st.st_size)
2083 static const char zero;
2085 /* extend the file one byte beyond the requested size and then truncate it */
2086 /* this should work around ftruncate implementations that can't extend files */
2087 if (pwrite( fd, &zero, 1, (off_t)info->EndOfFile.QuadPart ) != -1 &&
2088 ftruncate( fd, (off_t)info->EndOfFile.QuadPart ) != -1) break;
2090 io->u.Status = FILE_GetNtStatus();
2092 if (needs_close) close( fd );
2094 else io->u.Status = STATUS_INVALID_PARAMETER_3;
2095 break;
2097 case FileMailslotSetInformation:
2099 FILE_MAILSLOT_SET_INFORMATION *info = ptr;
2101 SERVER_START_REQ( set_mailslot_info )
2103 req->handle = wine_server_obj_handle( handle );
2104 req->flags = MAILSLOT_SET_READ_TIMEOUT;
2105 req->read_timeout = info->ReadTimeout.QuadPart;
2106 io->u.Status = wine_server_call( req );
2108 SERVER_END_REQ;
2110 break;
2112 case FileCompletionInformation:
2113 if (len >= sizeof(FILE_COMPLETION_INFORMATION))
2115 FILE_COMPLETION_INFORMATION *info = ptr;
2117 SERVER_START_REQ( set_completion_info )
2119 req->handle = wine_server_obj_handle( handle );
2120 req->chandle = wine_server_obj_handle( info->CompletionPort );
2121 req->ckey = info->CompletionKey;
2122 io->u.Status = wine_server_call( req );
2124 SERVER_END_REQ;
2125 } else
2126 io->u.Status = STATUS_INVALID_PARAMETER_3;
2127 break;
2129 default:
2130 FIXME("Unsupported class (%d)\n", class);
2131 io->u.Status = STATUS_NOT_IMPLEMENTED;
2132 break;
2134 io->Information = 0;
2135 return io->u.Status;
2139 /******************************************************************************
2140 * NtQueryFullAttributesFile (NTDLL.@)
2142 NTSTATUS WINAPI NtQueryFullAttributesFile( const OBJECT_ATTRIBUTES *attr,
2143 FILE_NETWORK_OPEN_INFORMATION *info )
2145 ANSI_STRING unix_name;
2146 NTSTATUS status;
2148 if (!(status = nt_to_unix_file_name_attr( attr, &unix_name, FILE_OPEN )))
2150 struct stat st;
2152 if (stat( unix_name.Buffer, &st ) == -1)
2153 status = FILE_GetNtStatus();
2154 else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
2155 status = STATUS_INVALID_INFO_CLASS;
2156 else
2158 FILE_BASIC_INFORMATION basic;
2159 FILE_STANDARD_INFORMATION std;
2161 fill_stat_info( &st, &basic, FileBasicInformation );
2162 fill_stat_info( &st, &std, FileStandardInformation );
2164 info->CreationTime = basic.CreationTime;
2165 info->LastAccessTime = basic.LastAccessTime;
2166 info->LastWriteTime = basic.LastWriteTime;
2167 info->ChangeTime = basic.ChangeTime;
2168 info->AllocationSize = std.AllocationSize;
2169 info->EndOfFile = std.EndOfFile;
2170 info->FileAttributes = basic.FileAttributes;
2171 if (DIR_is_hidden_file( attr->ObjectName ))
2172 info->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
2174 RtlFreeAnsiString( &unix_name );
2176 else WARN("%s not found (%x)\n", debugstr_us(attr->ObjectName), status );
2177 return status;
2181 /******************************************************************************
2182 * NtQueryAttributesFile (NTDLL.@)
2183 * ZwQueryAttributesFile (NTDLL.@)
2185 NTSTATUS WINAPI NtQueryAttributesFile( const OBJECT_ATTRIBUTES *attr, FILE_BASIC_INFORMATION *info )
2187 ANSI_STRING unix_name;
2188 NTSTATUS status;
2190 if (!(status = nt_to_unix_file_name_attr( attr, &unix_name, FILE_OPEN )))
2192 struct stat st;
2194 if (stat( unix_name.Buffer, &st ) == -1)
2195 status = FILE_GetNtStatus();
2196 else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
2197 status = STATUS_INVALID_INFO_CLASS;
2198 else
2200 status = fill_stat_info( &st, info, FileBasicInformation );
2201 if (DIR_is_hidden_file( attr->ObjectName ))
2202 info->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
2204 RtlFreeAnsiString( &unix_name );
2206 else WARN("%s not found (%x)\n", debugstr_us(attr->ObjectName), status );
2207 return status;
2211 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
2212 /* helper for FILE_GetDeviceInfo to hide some platform differences in fstatfs */
2213 static inline void get_device_info_fstatfs( FILE_FS_DEVICE_INFORMATION *info, const char *fstypename,
2214 unsigned int flags )
2216 if (!strcmp("cd9660", fstypename) || !strcmp("udf", fstypename))
2218 info->DeviceType = FILE_DEVICE_CD_ROM_FILE_SYSTEM;
2219 /* Don't assume read-only, let the mount options set it below */
2220 info->Characteristics |= FILE_REMOVABLE_MEDIA;
2222 else if (!strcmp("nfs", fstypename) || !strcmp("nwfs", fstypename) ||
2223 !strcmp("smbfs", fstypename) || !strcmp("afpfs", fstypename))
2225 info->DeviceType = FILE_DEVICE_NETWORK_FILE_SYSTEM;
2226 info->Characteristics |= FILE_REMOTE_DEVICE;
2228 else if (!strcmp("procfs", fstypename))
2229 info->DeviceType = FILE_DEVICE_VIRTUAL_DISK;
2230 else
2231 info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
2233 if (flags & MNT_RDONLY)
2234 info->Characteristics |= FILE_READ_ONLY_DEVICE;
2236 if (!(flags & MNT_LOCAL))
2238 info->DeviceType = FILE_DEVICE_NETWORK_FILE_SYSTEM;
2239 info->Characteristics |= FILE_REMOTE_DEVICE;
2242 #endif
2244 static inline int is_device_placeholder( int fd )
2246 static const char wine_placeholder[] = "Wine device placeholder";
2247 char buffer[sizeof(wine_placeholder)-1];
2249 if (pread( fd, buffer, sizeof(wine_placeholder) - 1, 0 ) != sizeof(wine_placeholder) - 1)
2250 return 0;
2251 return !memcmp( buffer, wine_placeholder, sizeof(wine_placeholder) - 1 );
2254 /******************************************************************************
2255 * get_device_info
2257 * Implementation of the FileFsDeviceInformation query for NtQueryVolumeInformationFile.
2259 static NTSTATUS get_device_info( int fd, FILE_FS_DEVICE_INFORMATION *info )
2261 struct stat st;
2263 info->Characteristics = 0;
2264 if (fstat( fd, &st ) < 0) return FILE_GetNtStatus();
2265 if (S_ISCHR( st.st_mode ))
2267 info->DeviceType = FILE_DEVICE_UNKNOWN;
2268 #ifdef linux
2269 switch(major(st.st_rdev))
2271 case MEM_MAJOR:
2272 info->DeviceType = FILE_DEVICE_NULL;
2273 break;
2274 case TTY_MAJOR:
2275 info->DeviceType = FILE_DEVICE_SERIAL_PORT;
2276 break;
2277 case LP_MAJOR:
2278 info->DeviceType = FILE_DEVICE_PARALLEL_PORT;
2279 break;
2280 case SCSI_TAPE_MAJOR:
2281 info->DeviceType = FILE_DEVICE_TAPE;
2282 break;
2284 #endif
2286 else if (S_ISBLK( st.st_mode ))
2288 info->DeviceType = FILE_DEVICE_DISK;
2290 else if (S_ISFIFO( st.st_mode ) || S_ISSOCK( st.st_mode ))
2292 info->DeviceType = FILE_DEVICE_NAMED_PIPE;
2294 else if (is_device_placeholder( fd ))
2296 info->DeviceType = FILE_DEVICE_DISK;
2298 else /* regular file or directory */
2300 #if defined(linux) && defined(HAVE_FSTATFS)
2301 struct statfs stfs;
2303 /* check for floppy disk */
2304 if (major(st.st_dev) == FLOPPY_MAJOR)
2305 info->Characteristics |= FILE_REMOVABLE_MEDIA;
2307 if (fstatfs( fd, &stfs ) < 0) stfs.f_type = 0;
2308 switch (stfs.f_type)
2310 case 0x9660: /* iso9660 */
2311 case 0x9fa1: /* supermount */
2312 case 0x15013346: /* udf */
2313 info->DeviceType = FILE_DEVICE_CD_ROM_FILE_SYSTEM;
2314 info->Characteristics |= FILE_REMOVABLE_MEDIA|FILE_READ_ONLY_DEVICE;
2315 break;
2316 case 0x6969: /* nfs */
2317 case 0x517B: /* smbfs */
2318 case 0x564c: /* ncpfs */
2319 info->DeviceType = FILE_DEVICE_NETWORK_FILE_SYSTEM;
2320 info->Characteristics |= FILE_REMOTE_DEVICE;
2321 break;
2322 case 0x01021994: /* tmpfs */
2323 case 0x28cd3d45: /* cramfs */
2324 case 0x1373: /* devfs */
2325 case 0x9fa0: /* procfs */
2326 info->DeviceType = FILE_DEVICE_VIRTUAL_DISK;
2327 break;
2328 default:
2329 info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
2330 break;
2332 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__APPLE__)
2333 struct statfs stfs;
2335 if (fstatfs( fd, &stfs ) < 0)
2336 info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
2337 else
2338 get_device_info_fstatfs( info, stfs.f_fstypename, stfs.f_flags );
2339 #elif defined(__NetBSD__)
2340 struct statvfs stfs;
2342 if (fstatvfs( fd, &stfs) < 0)
2343 info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
2344 else
2345 get_device_info_fstatfs( info, stfs.f_fstypename, stfs.f_flag );
2346 #elif defined(sun)
2347 /* Use dkio to work out device types */
2349 # include <sys/dkio.h>
2350 # include <sys/vtoc.h>
2351 struct dk_cinfo dkinf;
2352 int retval = ioctl(fd, DKIOCINFO, &dkinf);
2353 if(retval==-1){
2354 WARN("Unable to get disk device type information - assuming a disk like device\n");
2355 info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
2357 switch (dkinf.dki_ctype)
2359 case DKC_CDROM:
2360 info->DeviceType = FILE_DEVICE_CD_ROM_FILE_SYSTEM;
2361 info->Characteristics |= FILE_REMOVABLE_MEDIA|FILE_READ_ONLY_DEVICE;
2362 break;
2363 case DKC_NCRFLOPPY:
2364 case DKC_SMSFLOPPY:
2365 case DKC_INTEL82072:
2366 case DKC_INTEL82077:
2367 info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
2368 info->Characteristics |= FILE_REMOVABLE_MEDIA;
2369 break;
2370 case DKC_MD:
2371 info->DeviceType = FILE_DEVICE_VIRTUAL_DISK;
2372 break;
2373 default:
2374 info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
2377 #else
2378 static int warned;
2379 if (!warned++) FIXME( "device info not properly supported on this platform\n" );
2380 info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
2381 #endif
2382 info->Characteristics |= FILE_DEVICE_IS_MOUNTED;
2384 return STATUS_SUCCESS;
2388 /******************************************************************************
2389 * NtQueryVolumeInformationFile [NTDLL.@]
2390 * ZwQueryVolumeInformationFile [NTDLL.@]
2392 * Get volume information for an open file handle.
2394 * PARAMS
2395 * handle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
2396 * io [O] Receives information about the operation on return
2397 * buffer [O] Destination for volume information
2398 * length [I] Size of FsInformation
2399 * info_class [I] Type of volume information to set
2401 * RETURNS
2402 * Success: 0. io and buffer are updated.
2403 * Failure: An NTSTATUS error code describing the error.
2405 NTSTATUS WINAPI NtQueryVolumeInformationFile( HANDLE handle, PIO_STATUS_BLOCK io,
2406 PVOID buffer, ULONG length,
2407 FS_INFORMATION_CLASS info_class )
2409 int fd, needs_close;
2410 struct stat st;
2411 static int once;
2413 if ((io->u.Status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )) != STATUS_SUCCESS)
2414 return io->u.Status;
2416 io->u.Status = STATUS_NOT_IMPLEMENTED;
2417 io->Information = 0;
2419 switch( info_class )
2421 case FileFsVolumeInformation:
2422 if (!once++) FIXME( "%p: volume info not supported\n", handle );
2423 break;
2424 case FileFsLabelInformation:
2425 FIXME( "%p: label info not supported\n", handle );
2426 break;
2427 case FileFsSizeInformation:
2428 if (length < sizeof(FILE_FS_SIZE_INFORMATION))
2429 io->u.Status = STATUS_BUFFER_TOO_SMALL;
2430 else
2432 FILE_FS_SIZE_INFORMATION *info = buffer;
2434 if (fstat( fd, &st ) < 0)
2436 io->u.Status = FILE_GetNtStatus();
2437 break;
2439 if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
2441 io->u.Status = STATUS_INVALID_DEVICE_REQUEST;
2443 else
2445 ULONGLONG bsize;
2446 /* Linux's fstatvfs is buggy */
2447 #if !defined(linux) || !defined(HAVE_FSTATFS)
2448 struct statvfs stfs;
2450 if (fstatvfs( fd, &stfs ) < 0)
2452 io->u.Status = FILE_GetNtStatus();
2453 break;
2455 bsize = stfs.f_frsize;
2456 #else
2457 struct statfs stfs;
2458 if (fstatfs( fd, &stfs ) < 0)
2460 io->u.Status = FILE_GetNtStatus();
2461 break;
2463 bsize = stfs.f_bsize;
2464 #endif
2465 if (bsize == 2048) /* assume CD-ROM */
2467 info->BytesPerSector = 2048;
2468 info->SectorsPerAllocationUnit = 1;
2470 else
2472 info->BytesPerSector = 512;
2473 info->SectorsPerAllocationUnit = 8;
2475 info->TotalAllocationUnits.QuadPart = bsize * stfs.f_blocks / (info->BytesPerSector * info->SectorsPerAllocationUnit);
2476 info->AvailableAllocationUnits.QuadPart = bsize * stfs.f_bavail / (info->BytesPerSector * info->SectorsPerAllocationUnit);
2477 io->Information = sizeof(*info);
2478 io->u.Status = STATUS_SUCCESS;
2481 break;
2482 case FileFsDeviceInformation:
2483 if (length < sizeof(FILE_FS_DEVICE_INFORMATION))
2484 io->u.Status = STATUS_BUFFER_TOO_SMALL;
2485 else
2487 FILE_FS_DEVICE_INFORMATION *info = buffer;
2489 if ((io->u.Status = get_device_info( fd, info )) == STATUS_SUCCESS)
2490 io->Information = sizeof(*info);
2492 break;
2493 case FileFsAttributeInformation:
2494 FIXME( "%p: attribute info not supported\n", handle );
2495 break;
2496 case FileFsControlInformation:
2497 FIXME( "%p: control info not supported\n", handle );
2498 break;
2499 case FileFsFullSizeInformation:
2500 FIXME( "%p: full size info not supported\n", handle );
2501 break;
2502 case FileFsObjectIdInformation:
2503 FIXME( "%p: object id info not supported\n", handle );
2504 break;
2505 case FileFsMaximumInformation:
2506 FIXME( "%p: maximum info not supported\n", handle );
2507 break;
2508 default:
2509 io->u.Status = STATUS_INVALID_PARAMETER;
2510 break;
2512 if (needs_close) close( fd );
2513 return io->u.Status;
2517 /******************************************************************
2518 * NtQueryEaFile (NTDLL.@)
2520 * Read extended attributes from NTFS files.
2522 * PARAMS
2523 * hFile [I] File handle, must be opened with FILE_READ_EA access
2524 * iosb [O] Receives information about the operation on return
2525 * buffer [O] Output buffer
2526 * length [I] Length of output buffer
2527 * single_entry [I] Only read and return one entry
2528 * ea_list [I] Optional list with names of EAs to return
2529 * ea_list_len [I] Length of ea_list in bytes
2530 * ea_index [I] Optional pointer to 1-based index of attribute to return
2531 * restart [I] restart EA scan
2533 * RETURNS
2534 * Success: 0. Atrributes read into buffer
2535 * Failure: An NTSTATUS error code describing the error.
2537 NTSTATUS WINAPI NtQueryEaFile( HANDLE hFile, PIO_STATUS_BLOCK iosb, PVOID buffer, ULONG length,
2538 BOOLEAN single_entry, PVOID ea_list, ULONG ea_list_len,
2539 PULONG ea_index, BOOLEAN restart )
2541 FIXME("(%p,%p,%p,%d,%d,%p,%d,%p,%d) stub\n",
2542 hFile, iosb, buffer, length, single_entry, ea_list,
2543 ea_list_len, ea_index, restart);
2544 return STATUS_ACCESS_DENIED;
2548 /******************************************************************
2549 * NtSetEaFile (NTDLL.@)
2551 * Update extended attributes for NTFS files.
2553 * PARAMS
2554 * hFile [I] File handle, must be opened with FILE_READ_EA access
2555 * iosb [O] Receives information about the operation on return
2556 * buffer [I] Buffer with EA information
2557 * length [I] Length of buffer
2559 * RETURNS
2560 * Success: 0. Attributes are updated
2561 * Failure: An NTSTATUS error code describing the error.
2563 NTSTATUS WINAPI NtSetEaFile( HANDLE hFile, PIO_STATUS_BLOCK iosb, PVOID buffer, ULONG length )
2565 FIXME("(%p,%p,%p,%d) stub\n", hFile, iosb, buffer, length);
2566 return STATUS_ACCESS_DENIED;
2570 /******************************************************************
2571 * NtFlushBuffersFile (NTDLL.@)
2573 * Flush any buffered data on an open file handle.
2575 * PARAMS
2576 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
2577 * IoStatusBlock [O] Receives information about the operation on return
2579 * RETURNS
2580 * Success: 0. IoStatusBlock is updated.
2581 * Failure: An NTSTATUS error code describing the error.
2583 NTSTATUS WINAPI NtFlushBuffersFile( HANDLE hFile, IO_STATUS_BLOCK* IoStatusBlock )
2585 NTSTATUS ret;
2586 HANDLE hEvent = NULL;
2588 SERVER_START_REQ( flush_file )
2590 req->handle = wine_server_obj_handle( hFile );
2591 ret = wine_server_call( req );
2592 hEvent = wine_server_ptr_handle( reply->event );
2594 SERVER_END_REQ;
2595 if (!ret && hEvent)
2597 ret = NtWaitForSingleObject( hEvent, FALSE, NULL );
2598 NtClose( hEvent );
2600 return ret;
2603 /******************************************************************
2604 * NtLockFile (NTDLL.@)
2608 NTSTATUS WINAPI NtLockFile( HANDLE hFile, HANDLE lock_granted_event,
2609 PIO_APC_ROUTINE apc, void* apc_user,
2610 PIO_STATUS_BLOCK io_status, PLARGE_INTEGER offset,
2611 PLARGE_INTEGER count, ULONG* key, BOOLEAN dont_wait,
2612 BOOLEAN exclusive )
2614 NTSTATUS ret;
2615 HANDLE handle;
2616 BOOLEAN async;
2617 static BOOLEAN warn = TRUE;
2619 if (apc || io_status || key)
2621 FIXME("Unimplemented yet parameter\n");
2622 return STATUS_NOT_IMPLEMENTED;
2625 if (apc_user && warn)
2627 FIXME("I/O completion on lock not implemented yet\n");
2628 warn = FALSE;
2631 for (;;)
2633 SERVER_START_REQ( lock_file )
2635 req->handle = wine_server_obj_handle( hFile );
2636 req->offset = offset->QuadPart;
2637 req->count = count->QuadPart;
2638 req->shared = !exclusive;
2639 req->wait = !dont_wait;
2640 ret = wine_server_call( req );
2641 handle = wine_server_ptr_handle( reply->handle );
2642 async = reply->overlapped;
2644 SERVER_END_REQ;
2645 if (ret != STATUS_PENDING)
2647 if (!ret && lock_granted_event) NtSetEvent(lock_granted_event, NULL);
2648 return ret;
2651 if (async)
2653 FIXME( "Async I/O lock wait not implemented, might deadlock\n" );
2654 if (handle) NtClose( handle );
2655 return STATUS_PENDING;
2657 if (handle)
2659 NtWaitForSingleObject( handle, FALSE, NULL );
2660 NtClose( handle );
2662 else
2664 LARGE_INTEGER time;
2666 /* Unix lock conflict, sleep a bit and retry */
2667 time.QuadPart = 100 * (ULONGLONG)10000;
2668 time.QuadPart = -time.QuadPart;
2669 NtDelayExecution( FALSE, &time );
2675 /******************************************************************
2676 * NtUnlockFile (NTDLL.@)
2680 NTSTATUS WINAPI NtUnlockFile( HANDLE hFile, PIO_STATUS_BLOCK io_status,
2681 PLARGE_INTEGER offset, PLARGE_INTEGER count,
2682 PULONG key )
2684 NTSTATUS status;
2686 TRACE( "%p %x%08x %x%08x\n",
2687 hFile, offset->u.HighPart, offset->u.LowPart, count->u.HighPart, count->u.LowPart );
2689 if (io_status || key)
2691 FIXME("Unimplemented yet parameter\n");
2692 return STATUS_NOT_IMPLEMENTED;
2695 SERVER_START_REQ( unlock_file )
2697 req->handle = wine_server_obj_handle( hFile );
2698 req->offset = offset->QuadPart;
2699 req->count = count->QuadPart;
2700 status = wine_server_call( req );
2702 SERVER_END_REQ;
2703 return status;
2706 /******************************************************************
2707 * NtCreateNamedPipeFile (NTDLL.@)
2711 NTSTATUS WINAPI NtCreateNamedPipeFile( PHANDLE handle, ULONG access,
2712 POBJECT_ATTRIBUTES attr, PIO_STATUS_BLOCK iosb,
2713 ULONG sharing, ULONG dispo, ULONG options,
2714 ULONG pipe_type, ULONG read_mode,
2715 ULONG completion_mode, ULONG max_inst,
2716 ULONG inbound_quota, ULONG outbound_quota,
2717 PLARGE_INTEGER timeout)
2719 NTSTATUS status;
2721 TRACE("(%p %x %s %p %x %d %x %d %d %d %d %d %d %p)\n",
2722 handle, access, debugstr_w(attr->ObjectName->Buffer), iosb, sharing, dispo,
2723 options, pipe_type, read_mode, completion_mode, max_inst, inbound_quota,
2724 outbound_quota, timeout);
2726 /* assume we only get relative timeout */
2727 if (timeout->QuadPart > 0)
2728 FIXME("Wrong time %s\n", wine_dbgstr_longlong(timeout->QuadPart));
2730 SERVER_START_REQ( create_named_pipe )
2732 req->access = access;
2733 req->attributes = attr->Attributes;
2734 req->rootdir = wine_server_obj_handle( attr->RootDirectory );
2735 req->options = options;
2736 req->flags =
2737 (pipe_type) ? NAMED_PIPE_MESSAGE_STREAM_WRITE : 0 |
2738 (read_mode) ? NAMED_PIPE_MESSAGE_STREAM_READ : 0 |
2739 (completion_mode) ? NAMED_PIPE_NONBLOCKING_MODE : 0;
2740 req->maxinstances = max_inst;
2741 req->outsize = outbound_quota;
2742 req->insize = inbound_quota;
2743 req->timeout = timeout->QuadPart;
2744 wine_server_add_data( req, attr->ObjectName->Buffer,
2745 attr->ObjectName->Length );
2746 status = wine_server_call( req );
2747 if (!status) *handle = wine_server_ptr_handle( reply->handle );
2749 SERVER_END_REQ;
2750 return status;
2753 /******************************************************************
2754 * NtDeleteFile (NTDLL.@)
2758 NTSTATUS WINAPI NtDeleteFile( POBJECT_ATTRIBUTES ObjectAttributes )
2760 NTSTATUS status;
2761 HANDLE hFile;
2762 IO_STATUS_BLOCK io;
2764 TRACE("%p\n", ObjectAttributes);
2765 status = NtCreateFile( &hFile, GENERIC_READ | GENERIC_WRITE | DELETE,
2766 ObjectAttributes, &io, NULL, 0,
2767 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
2768 FILE_OPEN, FILE_DELETE_ON_CLOSE, NULL, 0 );
2769 if (status == STATUS_SUCCESS) status = NtClose(hFile);
2770 return status;
2773 /******************************************************************
2774 * NtCancelIoFileEx (NTDLL.@)
2778 NTSTATUS WINAPI NtCancelIoFileEx( HANDLE hFile, PIO_STATUS_BLOCK iosb, PIO_STATUS_BLOCK io_status )
2780 LARGE_INTEGER timeout;
2782 TRACE("%p %p %p\n", hFile, iosb, io_status );
2784 SERVER_START_REQ( cancel_async )
2786 req->handle = wine_server_obj_handle( hFile );
2787 req->iosb = wine_server_client_ptr( iosb );
2788 req->only_thread = FALSE;
2789 io_status->u.Status = wine_server_call( req );
2791 SERVER_END_REQ;
2792 if (io_status->u.Status)
2793 return io_status->u.Status;
2795 /* Let some APC be run, so that we can run the remaining APCs on hFile
2796 * either the cancelation of the pending one, but also the execution
2797 * of the queued APC, but not yet run. This is needed to ensure proper
2798 * clean-up of allocated data.
2800 timeout.u.LowPart = timeout.u.HighPart = 0;
2801 NtDelayExecution( TRUE, &timeout );
2802 return io_status->u.Status;
2805 /******************************************************************
2806 * NtCancelIoFile (NTDLL.@)
2810 NTSTATUS WINAPI NtCancelIoFile( HANDLE hFile, PIO_STATUS_BLOCK io_status )
2812 LARGE_INTEGER timeout;
2814 TRACE("%p %p\n", hFile, io_status );
2816 SERVER_START_REQ( cancel_async )
2818 req->handle = wine_server_obj_handle( hFile );
2819 req->iosb = 0;
2820 req->only_thread = TRUE;
2821 io_status->u.Status = wine_server_call( req );
2823 SERVER_END_REQ;
2824 if (io_status->u.Status)
2825 return io_status->u.Status;
2827 /* Let some APC be run, so that we can run the remaining APCs on hFile
2828 * either the cancelation of the pending one, but also the execution
2829 * of the queued APC, but not yet run. This is needed to ensure proper
2830 * clean-up of allocated data.
2832 timeout.u.LowPart = timeout.u.HighPart = 0;
2833 NtDelayExecution( TRUE, &timeout );
2834 return io_status->u.Status;
2837 /******************************************************************************
2838 * NtCreateMailslotFile [NTDLL.@]
2839 * ZwCreateMailslotFile [NTDLL.@]
2841 * PARAMS
2842 * pHandle [O] pointer to receive the handle created
2843 * DesiredAccess [I] access mode (read, write, etc)
2844 * ObjectAttributes [I] fully qualified NT path of the mailslot
2845 * IoStatusBlock [O] receives completion status and other info
2846 * CreateOptions [I]
2847 * MailslotQuota [I]
2848 * MaxMessageSize [I]
2849 * TimeOut [I]
2851 * RETURNS
2852 * An NT status code
2854 NTSTATUS WINAPI NtCreateMailslotFile(PHANDLE pHandle, ULONG DesiredAccess,
2855 POBJECT_ATTRIBUTES attr, PIO_STATUS_BLOCK IoStatusBlock,
2856 ULONG CreateOptions, ULONG MailslotQuota, ULONG MaxMessageSize,
2857 PLARGE_INTEGER TimeOut)
2859 LARGE_INTEGER timeout;
2860 NTSTATUS ret;
2862 TRACE("%p %08x %p %p %08x %08x %08x %p\n",
2863 pHandle, DesiredAccess, attr, IoStatusBlock,
2864 CreateOptions, MailslotQuota, MaxMessageSize, TimeOut);
2866 if (!pHandle) return STATUS_ACCESS_VIOLATION;
2867 if (!attr) return STATUS_INVALID_PARAMETER;
2868 if (!attr->ObjectName) return STATUS_OBJECT_PATH_SYNTAX_BAD;
2871 * For a NULL TimeOut pointer set the default timeout value
2873 if (!TimeOut)
2874 timeout.QuadPart = -1;
2875 else
2876 timeout.QuadPart = TimeOut->QuadPart;
2878 SERVER_START_REQ( create_mailslot )
2880 req->access = DesiredAccess;
2881 req->attributes = attr->Attributes;
2882 req->rootdir = wine_server_obj_handle( attr->RootDirectory );
2883 req->max_msgsize = MaxMessageSize;
2884 req->read_timeout = timeout.QuadPart;
2885 wine_server_add_data( req, attr->ObjectName->Buffer,
2886 attr->ObjectName->Length );
2887 ret = wine_server_call( req );
2888 if( ret == STATUS_SUCCESS )
2889 *pHandle = wine_server_ptr_handle( reply->handle );
2891 SERVER_END_REQ;
2893 return ret;