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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 STATFS_DEFINED_BY_SYS_VFS
45 # ifdef STATFS_DEFINED_BY_SYS_MOUNT
46 # include <sys/mount.h>
48 # ifdef STATFS_DEFINED_BY_SYS_STATFS
49 # include <sys/statfs.h>
54 #define NONAMELESSUNION
55 #define NONAMELESSSTRUCT
56 #include "wine/unicode.h"
57 #include "wine/debug.h"
58 #include "wine/server.h"
60 #include "ntdll_misc.h"
65 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
67 /**************************************************************************
68 * NtOpenFile [NTDLL.@]
69 * ZwOpenFile [NTDLL.@]
74 * handle [O] Variable that receives the file handle on return
75 * access [I] Access desired by the caller to the file
76 * attr [I] Structue describing the file to be opened
77 * io [O] Receives details about the result of the operation
78 * sharing [I] Type of shared access the caller requires
79 * options [I] Options for the file open
82 * Success: 0. FileHandle and IoStatusBlock are updated.
83 * Failure: An NTSTATUS error code describing the error.
85 NTSTATUS WINAPI NtOpenFile( PHANDLE handle, ACCESS_MASK access,
86 POBJECT_ATTRIBUTES attr, PIO_STATUS_BLOCK io,
87 ULONG sharing, ULONG options )
89 return NtCreateFile( handle, access, attr, io, NULL, 0,
90 sharing, FILE_OPEN, options, NULL, 0 );
93 /**************************************************************************
94 * NtCreateFile [NTDLL.@]
95 * ZwCreateFile [NTDLL.@]
97 * Either create a new file or directory, or open an existing file, device,
98 * directory or volume.
101 * handle [O] Points to a variable which receives the file handle on return
102 * access [I] Desired access to the file
103 * attr [I] Structure describing the file
104 * io [O] Receives information about the operation on return
105 * alloc_size [I] Initial size of the file in bytes
106 * attributes [I] Attributes to create the file with
107 * sharing [I] Type of shared access the caller would like to the file
108 * disposition [I] Specifies what to do, depending on whether the file already exists
109 * options [I] Options for creating a new file
110 * ea_buffer [I] Undocumented
111 * ea_length [I] Undocumented
114 * Success: 0. handle and io are updated.
115 * Failure: An NTSTATUS error code describing the error.
117 NTSTATUS WINAPI NtCreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATTRIBUTES attr,
118 PIO_STATUS_BLOCK io, PLARGE_INTEGER alloc_size,
119 ULONG attributes, ULONG sharing, ULONG disposition,
120 ULONG options, PVOID ea_buffer, ULONG ea_length )
122 ANSI_STRING unix_name;
124 TRACE("handle=%p access=%08lx name=%s objattr=%08lx root=%p sec=%p io=%p alloc_size=%p\n"
125 "attr=%08lx sharing=%08lx disp=%ld options=%08lx ea=%p.0x%08lx\n",
126 handle, access, debugstr_us(attr->ObjectName), attr->Attributes,
127 attr->RootDirectory, attr->SecurityDescriptor, io, alloc_size,
128 attributes, sharing, disposition, options, ea_buffer, ea_length );
130 if (attr->RootDirectory)
132 FIXME( "RootDirectory %p not supported\n", attr->RootDirectory );
133 return STATUS_OBJECT_NAME_NOT_FOUND;
135 if (alloc_size) FIXME( "alloc_size not supported\n" );
137 if (!(io->u.Status = DIR_nt_to_unix( attr->ObjectName, &unix_name,
138 (disposition == FILE_OPEN || disposition == FILE_OVERWRITE),
139 !(attr->Attributes & OBJ_CASE_INSENSITIVE) )))
141 SERVER_START_REQ( create_file )
143 req->access = access;
144 req->inherit = (attr->Attributes & OBJ_INHERIT) != 0;
145 req->sharing = sharing;
146 req->create = disposition;
147 req->options = options;
148 req->attrs = attributes;
149 wine_server_add_data( req, unix_name.Buffer, unix_name.Length );
150 io->u.Status = wine_server_call( req );
151 *handle = reply->handle;
154 RtlFreeAnsiString( &unix_name );
156 else WARN("%s not found (%lx)\n", debugstr_us(attr->ObjectName), io->u.Status );
160 /***********************************************************************
161 * Asynchronous file I/O *
163 static DWORD fileio_get_async_count(const async_private *ovp);
164 static void CALLBACK fileio_call_completion_func(ULONG_PTR data);
165 static void fileio_async_cleanup(async_private *ovp);
167 static async_ops fileio_async_ops =
169 fileio_get_async_count, /* get_count */
170 fileio_call_completion_func, /* call_completion */
171 fileio_async_cleanup /* cleanup */
174 static async_ops fileio_nocomp_async_ops =
176 fileio_get_async_count, /* get_count */
177 NULL, /* call_completion */
178 fileio_async_cleanup /* cleanup */
181 typedef struct async_fileio
183 struct async_private async;
188 unsigned long offset;
189 enum fd_type fd_type;
192 static DWORD fileio_get_async_count(const struct async_private *ovp)
194 async_fileio *fileio = (async_fileio*) ovp;
196 if (fileio->count < fileio->async.iosb->Information)
198 return fileio->count - fileio->async.iosb->Information;
201 static void CALLBACK fileio_call_completion_func(ULONG_PTR data)
203 async_fileio *ovp = (async_fileio*) data;
204 TRACE("data: %p\n", ovp);
206 ovp->apc( ovp->apc_user, ovp->async.iosb, ovp->async.iosb->Information );
208 fileio_async_cleanup( &ovp->async );
211 static void fileio_async_cleanup( struct async_private *ovp )
213 RtlFreeHeap( GetProcessHeap(), 0, ovp );
216 /***********************************************************************
217 * FILE_GetNtStatus(void)
219 * Retrieve the Nt Status code from errno.
220 * Try to be consistent with FILE_SetDosError().
222 NTSTATUS FILE_GetNtStatus(void)
227 TRACE( "errno = %d\n", errno );
230 case EAGAIN: nt = STATUS_SHARING_VIOLATION; break;
231 case EBADF: nt = STATUS_INVALID_HANDLE; break;
232 case ENOSPC: nt = STATUS_DISK_FULL; break;
235 case EACCES: nt = STATUS_ACCESS_DENIED; break;
236 case ENOENT: nt = STATUS_OBJECT_NAME_NOT_FOUND; break;
237 case EISDIR: nt = STATUS_FILE_IS_A_DIRECTORY; break;
239 case ENFILE: nt = STATUS_NO_MORE_FILES; break;
241 case ENOTEMPTY: nt = STATUS_DIRECTORY_NOT_EMPTY; break;
242 case EPIPE: nt = STATUS_PIPE_BROKEN; break;
243 case EIO: nt = STATUS_DEVICE_NOT_READY; break;
244 case ENOEXEC: /* ?? */
245 case ESPIPE: /* ?? */
246 case EEXIST: /* ?? */
248 FIXME( "Converting errno %d to STATUS_UNSUCCESSFUL\n", err );
249 nt = STATUS_UNSUCCESSFUL;
254 /***********************************************************************
255 * FILE_AsyncReadService (INTERNAL)
257 * This function is called while the client is waiting on the
258 * server, so we can't make any server calls here.
260 static void FILE_AsyncReadService(async_private *ovp)
262 async_fileio *fileio = (async_fileio*) ovp;
263 IO_STATUS_BLOCK* io_status = fileio->async.iosb;
265 int already = io_status->Information;
267 TRACE("%p %p\n", io_status, fileio->buffer );
269 /* check to see if the data is ready (non-blocking) */
271 if ( fileio->fd_type == FD_TYPE_SOCKET )
272 result = read(ovp->fd, &fileio->buffer[already], fileio->count - already);
275 result = pread(ovp->fd, &fileio->buffer[already], fileio->count - already,
276 fileio->offset + already);
277 if ((result < 0) && (errno == ESPIPE))
278 result = read(ovp->fd, &fileio->buffer[already], fileio->count - already);
281 if ((result < 0) && ((errno == EAGAIN) || (errno == EINTR)))
283 TRACE("Deferred read %d\n",errno);
284 io_status->u.Status = STATUS_PENDING;
288 /* check to see if the transfer is complete */
291 io_status->u.Status = FILE_GetNtStatus();
294 else if (result == 0)
296 io_status->u.Status = io_status->Information ? STATUS_SUCCESS : STATUS_END_OF_FILE;
300 io_status->Information += result;
301 if (io_status->Information >= fileio->count || fileio->fd_type == FD_TYPE_SOCKET )
302 io_status->u.Status = STATUS_SUCCESS;
304 io_status->u.Status = STATUS_PENDING;
306 TRACE("read %d more bytes %ld/%d so far\n",
307 result, io_status->Information, fileio->count);
311 /******************************************************************************
312 * NtReadFile [NTDLL.@]
313 * ZwReadFile [NTDLL.@]
315 * Read from an open file handle.
318 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
319 * Event [I] Event to signal upon completion (or NULL)
320 * ApcRoutine [I] Callback to call upon completion (or NULL)
321 * ApcContext [I] Context for ApcRoutine (or NULL)
322 * IoStatusBlock [O] Receives information about the operation on return
323 * Buffer [O] Destination for the data read
324 * Length [I] Size of Buffer
325 * ByteOffset [O] Destination for the new file pointer position (or NULL)
326 * Key [O] Function unknown (may be NULL)
329 * Success: 0. IoStatusBlock is updated, and the Information member contains
330 * The number of bytes read.
331 * Failure: An NTSTATUS error code describing the error.
333 NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
334 PIO_APC_ROUTINE apc, void* apc_user,
335 PIO_STATUS_BLOCK io_status, void* buffer, ULONG length,
336 PLARGE_INTEGER offset, PULONG key)
338 int unix_handle, flags;
341 TRACE("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%p),partial stub!\n",
342 hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
344 io_status->Information = 0;
345 io_status->u.Status = wine_server_handle_to_fd( hFile, GENERIC_READ, &unix_handle, &type, &flags );
346 if (io_status->u.Status) return io_status->u.Status;
348 if (flags & FD_FLAG_RECV_SHUTDOWN)
350 wine_server_release_fd( hFile, unix_handle );
351 return STATUS_PIPE_DISCONNECTED;
354 if (flags & FD_FLAG_TIMEOUT)
358 /* this shouldn't happen, but check it */
359 FIXME("NIY-hEvent\n");
360 wine_server_release_fd( hFile, unix_handle );
361 return STATUS_NOT_IMPLEMENTED;
363 io_status->u.Status = NtCreateEvent(&hEvent, SYNCHRONIZE, NULL, 0, 0);
364 if (io_status->u.Status)
366 wine_server_release_fd( hFile, unix_handle );
367 return io_status->u.Status;
371 if (flags & (FD_FLAG_OVERLAPPED|FD_FLAG_TIMEOUT))
376 if (!(ovp = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(async_fileio))))
378 wine_server_release_fd( hFile, unix_handle );
379 return STATUS_NO_MEMORY;
381 ovp->async.ops = (apc ? &fileio_async_ops : &fileio_nocomp_async_ops );
382 ovp->async.handle = hFile;
383 ovp->async.fd = unix_handle; /* FIXME */
384 ovp->async.type = ASYNC_TYPE_READ;
385 ovp->async.func = FILE_AsyncReadService;
386 ovp->async.event = hEvent;
387 ovp->async.iosb = io_status;
389 if ( offset == NULL )
393 ovp->offset = offset->u.LowPart;
394 if (offset->u.HighPart) FIXME("NIY-high part\n");
397 ovp->apc_user = apc_user;
398 ovp->buffer = buffer;
401 io_status->Information = 0;
402 ret = register_new_async(&ovp->async);
403 if (ret != STATUS_SUCCESS)
405 if (flags & FD_FLAG_TIMEOUT)
407 NtWaitForSingleObject(hEvent, TRUE, NULL);
412 LARGE_INTEGER timeout;
414 /* let some APC be run, this will read some already pending data */
415 timeout.u.LowPart = timeout.u.HighPart = 0;
416 NtDelayExecution( TRUE, &timeout );
418 return io_status->u.Status;
425 /* return SMB_ReadFile(hFile, unix_handle, buffer, length, io_status); */
426 wine_server_release_fd( hFile, unix_handle );
427 return STATUS_INVALID_HANDLE;
429 case FD_TYPE_DEFAULT:
430 /* normal unix file */
434 FIXME("Unsupported type of fd %d\n", type);
435 wine_server_release_fd( hFile, unix_handle );
436 return STATUS_INVALID_HANDLE;
441 FILE_POSITION_INFORMATION fpi;
443 fpi.CurrentByteOffset = *offset;
444 io_status->u.Status = NtSetInformationFile(hFile, io_status, &fpi, sizeof(fpi),
445 FilePositionInformation);
446 if (io_status->u.Status)
448 wine_server_release_fd( hFile, unix_handle );
449 return io_status->u.Status;
452 /* code for synchronous reads */
453 while ((io_status->Information = read( unix_handle, buffer, length )) == -1)
455 if ((errno == EAGAIN) || (errno == EINTR)) continue;
456 if (errno == EFAULT) FIXME( "EFAULT handling broken for now\n" );
457 io_status->u.Status = FILE_GetNtStatus();
460 wine_server_release_fd( hFile, unix_handle );
461 return io_status->u.Status;
464 /***********************************************************************
465 * FILE_AsyncWriteService (INTERNAL)
467 * This function is called while the client is waiting on the
468 * server, so we can't make any server calls here.
470 static void FILE_AsyncWriteService(struct async_private *ovp)
472 async_fileio *fileio = (async_fileio *) ovp;
473 PIO_STATUS_BLOCK io_status = fileio->async.iosb;
475 int already = io_status->Information;
477 TRACE("(%p %p)\n",io_status,fileio->buffer);
479 /* write some data (non-blocking) */
481 if ( fileio->fd_type == FD_TYPE_SOCKET )
482 result = write(ovp->fd, &fileio->buffer[already], fileio->count - already);
485 result = pwrite(ovp->fd, &fileio->buffer[already], fileio->count - already,
486 fileio->offset + already);
487 if ((result < 0) && (errno == ESPIPE))
488 result = write(ovp->fd, &fileio->buffer[already], fileio->count - already);
491 if ((result < 0) && ((errno == EAGAIN) || (errno == EINTR)))
493 io_status->u.Status = STATUS_PENDING;
497 /* check to see if the transfer is complete */
500 io_status->u.Status = FILE_GetNtStatus();
504 io_status->Information += result;
505 io_status->u.Status = (io_status->Information < fileio->count) ? STATUS_PENDING : STATUS_SUCCESS;
506 TRACE("wrote %d more bytes %ld/%d so far\n",result,io_status->Information,fileio->count);
509 /******************************************************************************
510 * NtWriteFile [NTDLL.@]
511 * ZwWriteFile [NTDLL.@]
513 * Write to an open file handle.
516 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
517 * Event [I] Event to signal upon completion (or NULL)
518 * ApcRoutine [I] Callback to call upon completion (or NULL)
519 * ApcContext [I] Context for ApcRoutine (or NULL)
520 * IoStatusBlock [O] Receives information about the operation on return
521 * Buffer [I] Source for the data to write
522 * Length [I] Size of Buffer
523 * ByteOffset [O] Destination for the new file pointer position (or NULL)
524 * Key [O] Function unknown (may be NULL)
527 * Success: 0. IoStatusBlock is updated, and the Information member contains
528 * The number of bytes written.
529 * Failure: An NTSTATUS error code describing the error.
531 NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
532 PIO_APC_ROUTINE apc, void* apc_user,
533 PIO_STATUS_BLOCK io_status,
534 const void* buffer, ULONG length,
535 PLARGE_INTEGER offset, PULONG key)
537 int unix_handle, flags;
540 TRACE("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%p)!\n",
541 hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
543 TRACE("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%p),partial stub!\n",
544 hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
546 io_status->Information = 0;
547 io_status->u.Status = wine_server_handle_to_fd( hFile, GENERIC_WRITE, &unix_handle, &type, &flags );
548 if (io_status->u.Status) return io_status->u.Status;
550 if (flags & FD_FLAG_SEND_SHUTDOWN)
552 wine_server_release_fd( hFile, unix_handle );
553 return STATUS_PIPE_DISCONNECTED;
556 if (flags & (FD_FLAG_OVERLAPPED|FD_FLAG_TIMEOUT))
561 if (!(ovp = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(async_fileio))))
563 wine_server_release_fd( hFile, unix_handle );
564 return STATUS_NO_MEMORY;
566 ovp->async.ops = (apc ? &fileio_async_ops : &fileio_nocomp_async_ops );
567 ovp->async.handle = hFile;
568 ovp->async.fd = unix_handle; /* FIXME */
569 ovp->async.type = ASYNC_TYPE_WRITE;
570 ovp->async.func = FILE_AsyncWriteService;
571 ovp->async.event = hEvent;
572 ovp->async.iosb = io_status;
575 ovp->offset = offset->u.LowPart;
576 if (offset->u.HighPart) FIXME("NIY-high part\n");
581 ovp->apc_user = apc_user;
582 ovp->buffer = (void*)buffer;
585 io_status->Information = 0;
586 ret = register_new_async(&ovp->async);
587 if (ret != STATUS_SUCCESS)
589 if (flags & FD_FLAG_TIMEOUT)
591 NtWaitForSingleObject(hEvent, TRUE, NULL);
596 LARGE_INTEGER timeout;
598 /* let some APC be run, this will write as much data as possible */
599 timeout.u.LowPart = timeout.u.HighPart = 0;
600 NtDelayExecution( TRUE, &timeout );
602 return io_status->u.Status;
608 wine_server_release_fd( hFile, unix_handle );
609 return STATUS_NOT_IMPLEMENTED;
611 case FD_TYPE_DEFAULT:
612 /* normal unix files */
613 if (unix_handle == -1) return STATUS_INVALID_HANDLE;
617 FIXME("Unsupported type of fd %d\n", type);
618 wine_server_release_fd( hFile, unix_handle );
619 return STATUS_INVALID_HANDLE;
624 FILE_POSITION_INFORMATION fpi;
626 fpi.CurrentByteOffset = *offset;
627 io_status->u.Status = NtSetInformationFile(hFile, io_status, &fpi, sizeof(fpi),
628 FilePositionInformation);
629 if (io_status->u.Status)
631 wine_server_release_fd( hFile, unix_handle );
632 return io_status->u.Status;
636 /* synchronous file write */
637 while ((io_status->Information = write( unix_handle, buffer, length )) == -1)
639 if ((errno == EAGAIN) || (errno == EINTR)) continue;
640 if (errno == EFAULT) FIXME( "EFAULT handling broken for now\n" );
641 if (errno == ENOSPC) io_status->u.Status = STATUS_DISK_FULL;
642 else io_status->u.Status = FILE_GetNtStatus();
645 wine_server_release_fd( hFile, unix_handle );
646 return io_status->u.Status;
649 /**************************************************************************
650 * NtDeviceIoControlFile [NTDLL.@]
651 * ZwDeviceIoControlFile [NTDLL.@]
653 * Perform an I/O control operation on an open file handle.
656 * DeviceHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
657 * Event [I] Event to signal upon completion (or NULL)
658 * ApcRoutine [I] Callback to call upon completion (or NULL)
659 * ApcContext [I] Context for ApcRoutine (or NULL)
660 * IoStatusBlock [O] Receives information about the operation on return
661 * IoControlCode [I] Control code for the operation to perform
662 * InputBuffer [I] Source for any input data required (or NULL)
663 * InputBufferSize [I] Size of InputBuffer
664 * OutputBuffer [O] Source for any output data returned (or NULL)
665 * OutputBufferSize [I] Size of OutputBuffer
668 * Success: 0. IoStatusBlock is updated.
669 * Failure: An NTSTATUS error code describing the error.
671 NTSTATUS WINAPI NtDeviceIoControlFile(HANDLE DeviceHandle, HANDLE hEvent,
672 PIO_APC_ROUTINE UserApcRoutine,
673 PVOID UserApcContext,
674 PIO_STATUS_BLOCK IoStatusBlock,
677 ULONG InputBufferSize,
679 ULONG OutputBufferSize)
681 TRACE("(%p,%p,%p,%p,%p,0x%08lx,%p,0x%08lx,%p,0x%08lx)\n",
682 DeviceHandle, hEvent, UserApcRoutine, UserApcContext,
683 IoStatusBlock, IoControlCode,
684 InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize);
686 if (CDROM_DeviceIoControl(DeviceHandle, hEvent,
687 UserApcRoutine, UserApcContext,
688 IoStatusBlock, IoControlCode,
689 InputBuffer, InputBufferSize,
690 OutputBuffer, OutputBufferSize) == STATUS_NO_SUCH_DEVICE)
692 /* it wasn't a CDROM */
693 FIXME("Unimplemented dwIoControlCode=%08lx\n", IoControlCode);
694 IoStatusBlock->u.Status = STATUS_NOT_IMPLEMENTED;
695 IoStatusBlock->Information = 0;
696 if (hEvent) NtSetEvent(hEvent, NULL);
698 return IoStatusBlock->u.Status;
701 /******************************************************************************
702 * NtFsControlFile [NTDLL.@]
703 * ZwFsControlFile [NTDLL.@]
705 NTSTATUS WINAPI NtFsControlFile(
706 IN HANDLE DeviceHandle,
707 IN HANDLE Event OPTIONAL,
708 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
709 IN PVOID ApcContext OPTIONAL,
710 OUT PIO_STATUS_BLOCK IoStatusBlock,
711 IN ULONG IoControlCode,
712 IN PVOID InputBuffer,
713 IN ULONG InputBufferSize,
714 OUT PVOID OutputBuffer,
715 IN ULONG OutputBufferSize)
717 FIXME("(%p,%p,%p,%p,%p,0x%08lx,%p,0x%08lx,%p,0x%08lx): stub\n",
718 DeviceHandle,Event,ApcRoutine,ApcContext,IoStatusBlock,IoControlCode,
719 InputBuffer,InputBufferSize,OutputBuffer,OutputBufferSize);
723 /******************************************************************************
724 * NtSetVolumeInformationFile [NTDLL.@]
725 * ZwSetVolumeInformationFile [NTDLL.@]
727 * Set volume information for an open file handle.
730 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
731 * IoStatusBlock [O] Receives information about the operation on return
732 * FsInformation [I] Source for volume information
733 * Length [I] Size of FsInformation
734 * FsInformationClass [I] Type of volume information to set
737 * Success: 0. IoStatusBlock is updated.
738 * Failure: An NTSTATUS error code describing the error.
740 NTSTATUS WINAPI NtSetVolumeInformationFile(
741 IN HANDLE FileHandle,
742 PIO_STATUS_BLOCK IoStatusBlock,
745 FS_INFORMATION_CLASS FsInformationClass)
747 FIXME("(%p,%p,%p,0x%08lx,0x%08x) stub\n",
748 FileHandle,IoStatusBlock,FsInformation,Length,FsInformationClass);
752 /******************************************************************************
753 * NtQueryInformationFile [NTDLL.@]
754 * ZwQueryInformationFile [NTDLL.@]
756 * Get information about an open file handle.
759 * hFile [I] Handle returned from ZwOpenFile() or ZwCreateFile()
760 * io [O] Receives information about the operation on return
761 * ptr [O] Destination for file information
762 * len [I] Size of FileInformation
763 * class [I] Type of file information to get
766 * Success: 0. IoStatusBlock and FileInformation are updated.
767 * Failure: An NTSTATUS error code describing the error.
769 NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
770 PVOID ptr, LONG len, FILE_INFORMATION_CLASS class )
774 TRACE("(%p,%p,%p,0x%08lx,0x%08x)\n", hFile, io, ptr, len, class);
777 if ((io->u.Status = wine_server_handle_to_fd( hFile, 0, &fd, NULL, NULL )))
782 case FileBasicInformation:
784 FILE_BASIC_INFORMATION *info = ptr;
786 if (len < sizeof(*info)) io->u.Status = STATUS_INFO_LENGTH_MISMATCH;
791 if (fstat( fd, &st ) == -1)
792 io->u.Status = FILE_GetNtStatus();
793 else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
794 io->u.Status = STATUS_INVALID_INFO_CLASS;
797 if (S_ISDIR(st.st_mode)) info->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
798 else info->FileAttributes = FILE_ATTRIBUTE_ARCHIVE;
799 if (!(st.st_mode & S_IWUSR)) info->FileAttributes |= FILE_ATTRIBUTE_READONLY;
800 RtlSecondsSince1970ToTime( st.st_mtime, &info->CreationTime);
801 RtlSecondsSince1970ToTime( st.st_mtime, &info->LastWriteTime);
802 RtlSecondsSince1970ToTime( st.st_ctime, &info->ChangeTime);
803 RtlSecondsSince1970ToTime( st.st_atime, &info->LastAccessTime);
808 case FileStandardInformation:
810 FILE_STANDARD_INFORMATION *info = ptr;
812 if (len < sizeof(*info)) io->u.Status = STATUS_INFO_LENGTH_MISMATCH;
817 if (fstat( fd, &st ) == -1) io->u.Status = FILE_GetNtStatus();
820 if ((info->Directory = S_ISDIR(st.st_mode)))
822 info->AllocationSize.QuadPart = 0;
823 info->EndOfFile.QuadPart = 0;
824 info->NumberOfLinks = 1;
825 info->DeletePending = FALSE;
829 info->AllocationSize.QuadPart = (ULONGLONG)st.st_blocks * 512;
830 info->EndOfFile.QuadPart = st.st_size;
831 info->NumberOfLinks = st.st_nlink;
832 info->DeletePending = FALSE; /* FIXME */
834 io->Information = sizeof(*info);
839 case FilePositionInformation:
841 FILE_POSITION_INFORMATION *info = ptr;
843 if (len < sizeof(*info)) io->u.Status = STATUS_INFO_LENGTH_MISMATCH;
846 off_t res = lseek( fd, 0, SEEK_CUR );
847 if (res == (off_t)-1) io->u.Status = FILE_GetNtStatus();
850 info->CurrentByteOffset.QuadPart = res;
851 io->Information = sizeof(*info);
857 FIXME("Unsupported class (%d)\n", class);
858 io->u.Status = STATUS_NOT_IMPLEMENTED;
861 wine_server_release_fd( hFile, fd );
865 /******************************************************************************
866 * NtSetInformationFile [NTDLL.@]
867 * ZwSetInformationFile [NTDLL.@]
869 * Set information about an open file handle.
872 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
873 * IoStatusBlock [O] Receives information about the operation on return
874 * FileInformation [I] Source for file information
875 * Length [I] Size of FileInformation
876 * FileInformationClass [I] Type of file information to set
879 * Success: 0. IoStatusBlock is updated.
880 * Failure: An NTSTATUS error code describing the error.
882 NTSTATUS WINAPI NtSetInformationFile(HANDLE hFile, PIO_STATUS_BLOCK io_status,
883 PVOID ptr, ULONG len,
884 FILE_INFORMATION_CLASS class)
886 NTSTATUS status = STATUS_INVALID_PARAMETER_3;
888 TRACE("(%p,%p,%p,0x%08lx,0x%08x)\n", hFile, io_status, ptr, len, class);
892 case FilePositionInformation:
893 if (len >= sizeof(FILE_POSITION_INFORMATION))
896 FILE_POSITION_INFORMATION* fpi = (FILE_POSITION_INFORMATION*)ptr;
898 if (!(status = wine_server_handle_to_fd( hFile, 0, &fd, NULL, NULL )))
900 if (lseek( fd, fpi->CurrentByteOffset.QuadPart, SEEK_SET ) == (off_t)-1)
901 status = FILE_GetNtStatus();
902 wine_server_release_fd( hFile, fd );
907 FIXME("Unsupported class (%d)\n", class);
908 return STATUS_NOT_IMPLEMENTED;
910 io_status->u.Status = status;
911 io_status->Information = 0;
916 /******************************************************************************
917 * NtQueryVolumeInformationFile [NTDLL.@]
918 * ZwQueryVolumeInformationFile [NTDLL.@]
920 * Get volume information for an open file handle.
923 * handle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
924 * io [O] Receives information about the operation on return
925 * buffer [O] Destination for volume information
926 * length [I] Size of FsInformation
927 * info_class [I] Type of volume information to set
930 * Success: 0. io and buffer are updated.
931 * Failure: An NTSTATUS error code describing the error.
933 NTSTATUS WINAPI NtQueryVolumeInformationFile( HANDLE handle, PIO_STATUS_BLOCK io,
934 PVOID buffer, ULONG length,
935 FS_INFORMATION_CLASS info_class )
940 if ((io->u.Status = wine_server_handle_to_fd( handle, 0, &fd, NULL, NULL )) != STATUS_SUCCESS)
943 io->u.Status = STATUS_NOT_IMPLEMENTED;
948 case FileFsVolumeInformation:
949 FIXME( "%p: volume info not supported\n", handle );
951 case FileFsLabelInformation:
952 FIXME( "%p: label info not supported\n", handle );
954 case FileFsSizeInformation:
955 if (length < sizeof(FILE_FS_SIZE_INFORMATION))
956 io->u.Status = STATUS_BUFFER_TOO_SMALL;
959 FILE_FS_SIZE_INFORMATION *info = buffer;
960 struct statvfs stvfs;
962 if (fstat( fd, &st ) < 0)
964 io->u.Status = FILE_GetNtStatus();
967 if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
969 io->u.Status = STATUS_INVALID_DEVICE_REQUEST;
972 if (fstatvfs( fd, &stvfs ) < 0) io->u.Status = FILE_GetNtStatus();
975 info->TotalAllocationUnits.QuadPart = stvfs.f_blocks;
976 info->AvailableAllocationUnits.QuadPart = stvfs.f_bavail;
977 info->SectorsPerAllocationUnit = 1;
978 info->BytesPerSector = stvfs.f_frsize;
979 io->Information = sizeof(*info);
980 io->u.Status = STATUS_SUCCESS;
984 case FileFsDeviceInformation:
985 if (length < sizeof(FILE_FS_DEVICE_INFORMATION))
986 io->u.Status = STATUS_BUFFER_TOO_SMALL;
989 FILE_FS_DEVICE_INFORMATION *info = buffer;
991 #if defined(linux) && defined(HAVE_FSTATFS)
994 info->Characteristics = 0;
996 if (fstat( fd, &st ) < 0)
998 io->u.Status = FILE_GetNtStatus();
1001 if (S_ISCHR( st.st_mode ))
1003 switch(major(st.st_rdev))
1006 info->DeviceType = FILE_DEVICE_NULL;
1009 info->DeviceType = FILE_DEVICE_SERIAL_PORT;
1012 info->DeviceType = FILE_DEVICE_PARALLEL_PORT;
1015 info->DeviceType = FILE_DEVICE_UNKNOWN;
1019 else if (S_ISBLK( st.st_mode ))
1021 info->DeviceType = FILE_DEVICE_DISK;
1023 else if (S_ISFIFO( st.st_mode ) || S_ISSOCK( st.st_mode ))
1025 info->DeviceType = FILE_DEVICE_NAMED_PIPE;
1027 else /* regular file or directory */
1029 info->Characteristics |= FILE_DEVICE_IS_MOUNTED;
1031 /* check for floppy disk */
1032 if (major(st.st_dev) == FLOPPY_MAJOR)
1033 info->Characteristics |= FILE_REMOVABLE_MEDIA;
1035 if (fstatfs( fd, &stfs ) < 0) stfs.f_type = 0;
1036 switch (stfs.f_type)
1038 case 0x9660: /* iso9660 */
1039 case 0x15013346: /* udf */
1040 info->DeviceType = FILE_DEVICE_CD_ROM_FILE_SYSTEM;
1041 info->Characteristics |= FILE_REMOVABLE_MEDIA|FILE_READ_ONLY_DEVICE;
1043 case 0x6969: /* nfs */
1044 case 0x517B: /* smbfs */
1045 case 0x564c: /* ncpfs */
1046 info->DeviceType = FILE_DEVICE_NETWORK_FILE_SYSTEM;
1047 info->Characteristics |= FILE_REMOTE_DEVICE;
1049 case 0x01021994: /* tmpfs */
1050 case 0x28cd3d45: /* cramfs */
1051 case 0x1373: /* devfs */
1052 case 0x9fa0: /* procfs */
1053 info->DeviceType = FILE_DEVICE_VIRTUAL_DISK;
1056 info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
1062 if (!warned++) FIXME( "device info not supported on this platform\n" );
1063 info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
1064 info->Characteristics = 0;
1066 io->Information = sizeof(*info);
1067 io->u.Status = STATUS_SUCCESS;
1070 case FileFsAttributeInformation:
1071 FIXME( "%p: attribute info not supported\n", handle );
1073 case FileFsControlInformation:
1074 FIXME( "%p: control info not supported\n", handle );
1076 case FileFsFullSizeInformation:
1077 FIXME( "%p: full size info not supported\n", handle );
1079 case FileFsObjectIdInformation:
1080 FIXME( "%p: object id info not supported\n", handle );
1082 case FileFsMaximumInformation:
1083 FIXME( "%p: maximum info not supported\n", handle );
1086 io->u.Status = STATUS_INVALID_PARAMETER;
1089 wine_server_release_fd( handle, fd );
1090 return io->u.Status;
1094 /******************************************************************
1095 * NtFlushBuffersFile (NTDLL.@)
1097 * Flush any buffered data on an open file handle.
1100 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
1101 * IoStatusBlock [O] Receives information about the operation on return
1104 * Success: 0. IoStatusBlock is updated.
1105 * Failure: An NTSTATUS error code describing the error.
1107 NTSTATUS WINAPI NtFlushBuffersFile( HANDLE hFile, IO_STATUS_BLOCK* IoStatusBlock )
1110 HANDLE hEvent = NULL;
1112 SERVER_START_REQ( flush_file )
1114 req->handle = hFile;
1115 ret = wine_server_call( req );
1116 hEvent = reply->event;
1121 ret = NtWaitForSingleObject( hEvent, FALSE, NULL );
1127 /******************************************************************
1128 * NtLockFile (NTDLL.@)
1132 NTSTATUS WINAPI NtLockFile( HANDLE hFile, HANDLE lock_granted_event,
1133 PIO_APC_ROUTINE apc, void* apc_user,
1134 PIO_STATUS_BLOCK io_status, PLARGE_INTEGER offset,
1135 PLARGE_INTEGER count, ULONG* key, BOOLEAN dont_wait,
1142 if (apc || io_status || key)
1144 FIXME("Unimplemented yet parameter\n");
1145 return STATUS_NOT_IMPLEMENTED;
1150 SERVER_START_REQ( lock_file )
1152 req->handle = hFile;
1153 req->offset_low = offset->u.LowPart;
1154 req->offset_high = offset->u.HighPart;
1155 req->count_low = count->u.LowPart;
1156 req->count_high = count->u.HighPart;
1157 req->shared = !exclusive;
1158 req->wait = !dont_wait;
1159 ret = wine_server_call( req );
1160 handle = reply->handle;
1161 async = reply->overlapped;
1164 if (ret != STATUS_PENDING)
1166 if (!ret && lock_granted_event) NtSetEvent(lock_granted_event, NULL);
1172 FIXME( "Async I/O lock wait not implemented, might deadlock\n" );
1173 if (handle) NtClose( handle );
1174 return STATUS_PENDING;
1178 NtWaitForSingleObject( handle, FALSE, NULL );
1185 /* Unix lock conflict, sleep a bit and retry */
1186 time.QuadPart = 100 * (ULONGLONG)10000;
1187 time.QuadPart = -time.QuadPart;
1188 NtDelayExecution( FALSE, &time );
1194 /******************************************************************
1195 * NtUnlockFile (NTDLL.@)
1199 NTSTATUS WINAPI NtUnlockFile( HANDLE hFile, PIO_STATUS_BLOCK io_status,
1200 PLARGE_INTEGER offset, PLARGE_INTEGER count,
1205 TRACE( "%p %lx%08lx %lx%08lx\n",
1206 hFile, offset->u.HighPart, offset->u.LowPart, count->u.HighPart, count->u.LowPart );
1208 if (io_status || key)
1210 FIXME("Unimplemented yet parameter\n");
1211 return STATUS_NOT_IMPLEMENTED;
1214 SERVER_START_REQ( unlock_file )
1216 req->handle = hFile;
1217 req->offset_low = offset->u.LowPart;
1218 req->offset_high = offset->u.HighPart;
1219 req->count_low = count->u.LowPart;
1220 req->count_high = count->u.HighPart;
1221 status = wine_server_call( req );