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>
34 #define NONAMELESSUNION
35 #define NONAMELESSSTRUCT
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
38 #include "wine/server.h"
40 #include "ntdll_misc.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
47 /**************************************************************************
48 * NtOpenFile [NTDLL.@]
49 * ZwOpenFile [NTDLL.@]
54 * FileHandle [O] Variable that receives the file handle on return
55 * DesiredAccess [I] Access desired by the caller to the file
56 * ObjectAttributes [I] Structue describing the file to be opened
57 * IoStatusBlock [O] Receives details about the result of the operation
58 * ShareAccess [I] Type of shared access the caller requires
59 * OpenOptions [I] Options for the file open
62 * Success: 0. FileHandle and IoStatusBlock are updated.
63 * Failure: An NTSTATUS error code describing the error.
65 NTSTATUS WINAPI NtOpenFile(
66 OUT PHANDLE FileHandle,
67 ACCESS_MASK DesiredAccess,
68 POBJECT_ATTRIBUTES ObjectAttributes,
69 OUT PIO_STATUS_BLOCK IoStatusBlock,
74 static const WCHAR szDosDevices[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\',0};
76 FIXME("(%p,0x%08lx,%p,%p,0x%08lx,0x%08lx) partial stub\n",
77 FileHandle, DesiredAccess, ObjectAttributes,
78 IoStatusBlock, ShareAccess, OpenOptions);
80 dump_ObjectAttributes (ObjectAttributes);
82 if(ObjectAttributes->RootDirectory)
84 FIXME("Object root directory unknown %p\n",
85 ObjectAttributes->RootDirectory);
86 return STATUS_OBJECT_NAME_NOT_FOUND;
89 filename = ObjectAttributes->ObjectName->Buffer;
91 /* FIXME: DOSFS stuff should call here, not vice-versa */
92 if(strncmpW(filename, szDosDevices, strlenW(szDosDevices)))
93 return STATUS_OBJECT_NAME_NOT_FOUND;
95 /* FIXME: this calls SetLastError() -> bad */
96 *FileHandle = pCreateFileW( &filename[strlenW(szDosDevices)], DesiredAccess, ShareAccess,
97 NULL, OPEN_EXISTING, 0, 0 );
98 if (*FileHandle == INVALID_HANDLE_VALUE) return STATUS_OBJECT_NAME_NOT_FOUND;
99 return STATUS_SUCCESS;
102 /**************************************************************************
103 * NtCreateFile [NTDLL.@]
104 * ZwCreateFile [NTDLL.@]
106 * Either create a new file or directory, or open an existing file, device,
107 * directory or volume.
110 * FileHandle [O] Points to a variable which receives the file handle on return
111 * DesiredAccess [I] Desired access to the file
112 * ObjectAttributes [I] Structure describing the file
113 * IoStatusBlock [O] Receives information about the operation on return
114 * AllocationSize [I] Initial size of the file in bytes
115 * FileAttributes [I] Attributes to create the file with
116 * ShareAccess [I] Type of shared access the caller would like to the file
117 * CreateDisposition [I] Specifies what to do, depending on whether the file already exists
118 * CreateOptions [I] Options for creating a new file
119 * EaBuffer [I] Undocumented
120 * EaLength [I] Undocumented
123 * Success: 0. FileHandle and IoStatusBlock are updated.
124 * Failure: An NTSTATUS error code describing the error.
126 NTSTATUS WINAPI NtCreateFile(
127 OUT PHANDLE FileHandle,
128 ACCESS_MASK DesiredAccess,
129 POBJECT_ATTRIBUTES ObjectAttributes,
130 OUT PIO_STATUS_BLOCK IoStatusBlock,
131 PLARGE_INTEGER AllocateSize,
132 ULONG FileAttributes,
134 ULONG CreateDisposition,
139 FIXME("(%p,0x%08lx,%p,%p,%p,0x%08lx,0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx) stub\n",
140 FileHandle,DesiredAccess,ObjectAttributes,
141 IoStatusBlock,AllocateSize,FileAttributes,
142 ShareAccess,CreateDisposition,CreateOptions,EaBuffer,EaLength);
143 dump_ObjectAttributes (ObjectAttributes);
147 /***********************************************************************
148 * Asynchronous file I/O *
150 static DWORD fileio_get_async_count(const async_private *ovp);
151 static void CALLBACK fileio_call_completion_func(ULONG_PTR data);
152 static void fileio_async_cleanup(async_private *ovp);
154 static async_ops fileio_async_ops =
156 fileio_get_async_count, /* get_count */
157 fileio_call_completion_func, /* call_completion */
158 fileio_async_cleanup /* cleanup */
161 static async_ops fileio_nocomp_async_ops =
163 fileio_get_async_count, /* get_count */
164 NULL, /* call_completion */
165 fileio_async_cleanup /* cleanup */
168 typedef struct async_fileio
170 struct async_private async;
175 unsigned long offset;
176 enum fd_type fd_type;
179 static DWORD fileio_get_async_count(const struct async_private *ovp)
181 async_fileio *fileio = (async_fileio*) ovp;
183 if (fileio->count < fileio->async.iosb->Information)
185 return fileio->count - fileio->async.iosb->Information;
188 static void CALLBACK fileio_call_completion_func(ULONG_PTR data)
190 async_fileio *ovp = (async_fileio*) data;
191 TRACE("data: %p\n", ovp);
193 ovp->apc( ovp->apc_user, ovp->async.iosb, ovp->async.iosb->Information );
195 fileio_async_cleanup( &ovp->async );
198 static void fileio_async_cleanup( struct async_private *ovp )
200 RtlFreeHeap( GetProcessHeap(), 0, ovp );
203 /***********************************************************************
204 * FILE_GetNtStatus(void)
206 * Retrieve the Nt Status code from errno.
207 * Try to be consistent with FILE_SetDosError().
209 NTSTATUS FILE_GetNtStatus(void)
214 TRACE( "errno = %d\n", errno );
217 case EAGAIN: nt = STATUS_SHARING_VIOLATION; break;
218 case EBADF: nt = STATUS_INVALID_HANDLE; break;
219 case ENOSPC: nt = STATUS_DISK_FULL; break;
222 case EACCES: nt = STATUS_ACCESS_DENIED; break;
223 case ENOENT: nt = STATUS_SHARING_VIOLATION; break;
224 case EISDIR: nt = STATUS_FILE_IS_A_DIRECTORY; break;
226 case ENFILE: nt = STATUS_NO_MORE_FILES; break;
228 case ENOTEMPTY: nt = STATUS_DIRECTORY_NOT_EMPTY; break;
229 case EPIPE: nt = STATUS_PIPE_BROKEN; break;
230 case EIO: nt = STATUS_DEVICE_NOT_READY; break;
231 case ENOEXEC: /* ?? */
232 case ESPIPE: /* ?? */
233 case EEXIST: /* ?? */
235 FIXME( "Converting errno %d to STATUS_UNSUCCESSFUL\n", err );
236 nt = STATUS_UNSUCCESSFUL;
241 /***********************************************************************
242 * FILE_AsyncReadService (INTERNAL)
244 * This function is called while the client is waiting on the
245 * server, so we can't make any server calls here.
247 static void FILE_AsyncReadService(async_private *ovp)
249 async_fileio *fileio = (async_fileio*) ovp;
250 IO_STATUS_BLOCK* io_status = fileio->async.iosb;
252 int already = io_status->Information;
254 TRACE("%p %p\n", io_status, fileio->buffer );
256 /* check to see if the data is ready (non-blocking) */
258 if ( fileio->fd_type == FD_TYPE_SOCKET )
259 result = read(ovp->fd, &fileio->buffer[already], fileio->count - already);
262 result = pread(ovp->fd, &fileio->buffer[already], fileio->count - already,
263 fileio->offset + already);
264 if ((result < 0) && (errno == ESPIPE))
265 result = read(ovp->fd, &fileio->buffer[already], fileio->count - already);
268 if ((result < 0) && ((errno == EAGAIN) || (errno == EINTR)))
270 TRACE("Deferred read %d\n",errno);
271 io_status->u.Status = STATUS_PENDING;
275 /* check to see if the transfer is complete */
278 io_status->u.Status = FILE_GetNtStatus();
281 else if (result == 0)
283 io_status->u.Status = io_status->Information ? STATUS_SUCCESS : STATUS_END_OF_FILE;
287 io_status->Information += result;
288 if (io_status->Information >= fileio->count || fileio->fd_type == FD_TYPE_SOCKET )
289 io_status->u.Status = STATUS_SUCCESS;
291 io_status->u.Status = STATUS_PENDING;
293 TRACE("read %d more bytes %ld/%d so far\n",
294 result, io_status->Information, fileio->count);
298 /******************************************************************************
299 * NtReadFile [NTDLL.@]
300 * ZwReadFile [NTDLL.@]
302 * Read from an open file handle.
305 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
306 * Event [I] Event to signal upon completion (or NULL)
307 * ApcRoutine [I] Callback to call upon completion (or NULL)
308 * ApcContext [I] Context for ApcRoutine (or NULL)
309 * IoStatusBlock [O] Receives information about the operation on return
310 * Buffer [O] Destination for the data read
311 * Length [I] Size of Buffer
312 * ByteOffset [O] Destination for the new file pointer position (or NULL)
313 * Key [O] Function unknown (may be NULL)
316 * Success: 0. IoStatusBlock is updated, and the Information member contains
317 * The number of bytes read.
318 * Failure: An NTSTATUS error code describing the error.
320 NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
321 PIO_APC_ROUTINE apc, void* apc_user,
322 PIO_STATUS_BLOCK io_status, void* buffer, ULONG length,
323 PLARGE_INTEGER offset, PULONG key)
325 int unix_handle, flags;
328 TRACE("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%p),partial stub!\n",
329 hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
331 io_status->Information = 0;
332 io_status->u.Status = wine_server_handle_to_fd( hFile, GENERIC_READ, &unix_handle, &type, &flags );
333 if (io_status->u.Status) return io_status->u.Status;
335 if (flags & FD_FLAG_RECV_SHUTDOWN)
337 wine_server_release_fd( hFile, unix_handle );
338 return STATUS_PIPE_DISCONNECTED;
341 if (flags & FD_FLAG_TIMEOUT)
345 /* this shouldn't happen, but check it */
346 FIXME("NIY-hEvent\n");
347 wine_server_release_fd( hFile, unix_handle );
348 return STATUS_NOT_IMPLEMENTED;
350 io_status->u.Status = NtCreateEvent(&hEvent, SYNCHRONIZE, NULL, 0, 0);
351 if (io_status->u.Status)
353 wine_server_release_fd( hFile, unix_handle );
354 return io_status->u.Status;
358 if (flags & (FD_FLAG_OVERLAPPED|FD_FLAG_TIMEOUT))
363 if (!(ovp = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(async_fileio))))
365 wine_server_release_fd( hFile, unix_handle );
366 return STATUS_NO_MEMORY;
368 ovp->async.ops = (apc ? &fileio_async_ops : &fileio_nocomp_async_ops );
369 ovp->async.handle = hFile;
370 ovp->async.fd = unix_handle; /* FIXME */
371 ovp->async.type = ASYNC_TYPE_READ;
372 ovp->async.func = FILE_AsyncReadService;
373 ovp->async.event = hEvent;
374 ovp->async.iosb = io_status;
376 if ( offset == NULL )
380 ovp->offset = offset->u.LowPart;
381 if (offset->u.HighPart) FIXME("NIY-high part\n");
384 ovp->apc_user = apc_user;
385 ovp->buffer = buffer;
388 io_status->Information = 0;
389 ret = register_new_async(&ovp->async);
390 if (ret != STATUS_SUCCESS)
392 if (flags & FD_FLAG_TIMEOUT)
394 NtWaitForSingleObject(hEvent, TRUE, NULL);
399 LARGE_INTEGER timeout;
401 /* let some APC be run, this will read some already pending data */
402 timeout.u.LowPart = timeout.u.HighPart = 0;
403 NtDelayExecution( TRUE, &timeout );
405 return io_status->u.Status;
412 /* return SMB_ReadFile(hFile, unix_handle, buffer, length, io_status); */
413 wine_server_release_fd( hFile, unix_handle );
414 return STATUS_INVALID_HANDLE;
416 case FD_TYPE_DEFAULT:
417 /* normal unix file */
421 FIXME("Unsupported type of fd %d\n", type);
422 wine_server_release_fd( hFile, unix_handle );
423 return STATUS_INVALID_HANDLE;
428 FILE_POSITION_INFORMATION fpi;
430 fpi.CurrentByteOffset = *offset;
431 io_status->u.Status = NtSetInformationFile(hFile, io_status, &fpi, sizeof(fpi),
432 FilePositionInformation);
433 if (io_status->u.Status)
435 wine_server_release_fd( hFile, unix_handle );
436 return io_status->u.Status;
439 /* code for synchronous reads */
440 while ((io_status->Information = read( unix_handle, buffer, length )) == -1)
442 if ((errno == EAGAIN) || (errno == EINTR)) continue;
443 if (errno == EFAULT) FIXME( "EFAULT handling broken for now\n" );
444 io_status->u.Status = FILE_GetNtStatus();
447 wine_server_release_fd( hFile, unix_handle );
448 return io_status->u.Status;
451 /***********************************************************************
452 * FILE_AsyncWriteService (INTERNAL)
454 * This function is called while the client is waiting on the
455 * server, so we can't make any server calls here.
457 static void FILE_AsyncWriteService(struct async_private *ovp)
459 async_fileio *fileio = (async_fileio *) ovp;
460 PIO_STATUS_BLOCK io_status = fileio->async.iosb;
462 int already = io_status->Information;
464 TRACE("(%p %p)\n",io_status,fileio->buffer);
466 /* write some data (non-blocking) */
468 if ( fileio->fd_type == FD_TYPE_SOCKET )
469 result = write(ovp->fd, &fileio->buffer[already], fileio->count - already);
472 result = pwrite(ovp->fd, &fileio->buffer[already], fileio->count - already,
473 fileio->offset + already);
474 if ((result < 0) && (errno == ESPIPE))
475 result = write(ovp->fd, &fileio->buffer[already], fileio->count - already);
478 if ((result < 0) && ((errno == EAGAIN) || (errno == EINTR)))
480 io_status->u.Status = STATUS_PENDING;
484 /* check to see if the transfer is complete */
487 io_status->u.Status = FILE_GetNtStatus();
491 io_status->Information += result;
492 io_status->u.Status = (io_status->Information < fileio->count) ? STATUS_PENDING : STATUS_SUCCESS;
493 TRACE("wrote %d more bytes %ld/%d so far\n",result,io_status->Information,fileio->count);
496 /******************************************************************************
497 * NtWriteFile [NTDLL.@]
498 * ZwWriteFile [NTDLL.@]
500 * Write to an open file handle.
503 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
504 * Event [I] Event to signal upon completion (or NULL)
505 * ApcRoutine [I] Callback to call upon completion (or NULL)
506 * ApcContext [I] Context for ApcRoutine (or NULL)
507 * IoStatusBlock [O] Receives information about the operation on return
508 * Buffer [I] Source for the data to write
509 * Length [I] Size of Buffer
510 * ByteOffset [O] Destination for the new file pointer position (or NULL)
511 * Key [O] Function unknown (may be NULL)
514 * Success: 0. IoStatusBlock is updated, and the Information member contains
515 * The number of bytes written.
516 * Failure: An NTSTATUS error code describing the error.
518 NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
519 PIO_APC_ROUTINE apc, void* apc_user,
520 PIO_STATUS_BLOCK io_status,
521 const void* buffer, ULONG length,
522 PLARGE_INTEGER offset, PULONG key)
524 int unix_handle, flags;
527 TRACE("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%p)!\n",
528 hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
530 TRACE("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%p),partial stub!\n",
531 hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
533 io_status->Information = 0;
534 io_status->u.Status = wine_server_handle_to_fd( hFile, GENERIC_WRITE, &unix_handle, &type, &flags );
535 if (io_status->u.Status) return io_status->u.Status;
537 if (flags & FD_FLAG_SEND_SHUTDOWN)
539 wine_server_release_fd( hFile, unix_handle );
540 return STATUS_PIPE_DISCONNECTED;
543 if (flags & (FD_FLAG_OVERLAPPED|FD_FLAG_TIMEOUT))
548 if (!(ovp = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(async_fileio))))
550 wine_server_release_fd( hFile, unix_handle );
551 return STATUS_NO_MEMORY;
553 ovp->async.ops = (apc ? &fileio_async_ops : &fileio_nocomp_async_ops );
554 ovp->async.handle = hFile;
555 ovp->async.fd = unix_handle; /* FIXME */
556 ovp->async.type = ASYNC_TYPE_WRITE;
557 ovp->async.func = FILE_AsyncWriteService;
558 ovp->async.event = hEvent;
559 ovp->async.iosb = io_status;
562 ovp->offset = offset->u.LowPart;
563 if (offset->u.HighPart) FIXME("NIY-high part\n");
568 ovp->apc_user = apc_user;
569 ovp->buffer = (void*)buffer;
572 io_status->Information = 0;
573 ret = register_new_async(&ovp->async);
574 if (ret != STATUS_SUCCESS)
576 if (flags & FD_FLAG_TIMEOUT)
578 NtWaitForSingleObject(hEvent, TRUE, NULL);
583 LARGE_INTEGER timeout;
585 /* let some APC be run, this will write as much data as possible */
586 timeout.u.LowPart = timeout.u.HighPart = 0;
587 NtDelayExecution( TRUE, &timeout );
589 return io_status->u.Status;
595 wine_server_release_fd( hFile, unix_handle );
596 return STATUS_NOT_IMPLEMENTED;
598 case FD_TYPE_DEFAULT:
599 /* normal unix files */
600 if (unix_handle == -1) return STATUS_INVALID_HANDLE;
604 FIXME("Unsupported type of fd %d\n", type);
605 wine_server_release_fd( hFile, unix_handle );
606 return STATUS_INVALID_HANDLE;
611 FILE_POSITION_INFORMATION fpi;
613 fpi.CurrentByteOffset = *offset;
614 io_status->u.Status = NtSetInformationFile(hFile, io_status, &fpi, sizeof(fpi),
615 FilePositionInformation);
616 if (io_status->u.Status)
618 wine_server_release_fd( hFile, unix_handle );
619 return io_status->u.Status;
623 /* synchronous file write */
624 while ((io_status->Information = write( unix_handle, buffer, length )) == -1)
626 if ((errno == EAGAIN) || (errno == EINTR)) continue;
627 if (errno == EFAULT) FIXME( "EFAULT handling broken for now\n" );
628 if (errno == ENOSPC) io_status->u.Status = STATUS_DISK_FULL;
629 else io_status->u.Status = FILE_GetNtStatus();
632 wine_server_release_fd( hFile, unix_handle );
633 return io_status->u.Status;
636 /**************************************************************************
637 * NtDeviceIoControlFile [NTDLL.@]
638 * ZwDeviceIoControlFile [NTDLL.@]
640 * Perform an I/O control operation on an open file handle.
643 * DeviceHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
644 * Event [I] Event to signal upon completion (or NULL)
645 * ApcRoutine [I] Callback to call upon completion (or NULL)
646 * ApcContext [I] Context for ApcRoutine (or NULL)
647 * IoStatusBlock [O] Receives information about the operation on return
648 * IoControlCode [I] Control code for the operation to perform
649 * InputBuffer [I] Source for any input data required (or NULL)
650 * InputBufferSize [I] Size of InputBuffer
651 * OutputBuffer [O] Source for any output data returned (or NULL)
652 * OutputBufferSize [I] Size of OutputBuffer
655 * Success: 0. IoStatusBlock is updated.
656 * Failure: An NTSTATUS error code describing the error.
658 NTSTATUS WINAPI NtDeviceIoControlFile(HANDLE DeviceHandle, HANDLE hEvent,
659 PIO_APC_ROUTINE UserApcRoutine,
660 PVOID UserApcContext,
661 PIO_STATUS_BLOCK IoStatusBlock,
664 ULONG InputBufferSize,
666 ULONG OutputBufferSize)
668 TRACE("(%p,%p,%p,%p,%p,0x%08lx,%p,0x%08lx,%p,0x%08lx)\n",
669 DeviceHandle, hEvent, UserApcRoutine, UserApcContext,
670 IoStatusBlock, IoControlCode,
671 InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize);
673 if (CDROM_DeviceIoControl(DeviceHandle, hEvent,
674 UserApcRoutine, UserApcContext,
675 IoStatusBlock, IoControlCode,
676 InputBuffer, InputBufferSize,
677 OutputBuffer, OutputBufferSize) == STATUS_NO_SUCH_DEVICE)
679 /* it wasn't a CDROM */
680 FIXME("Unimplemented dwIoControlCode=%08lx\n", IoControlCode);
681 IoStatusBlock->u.Status = STATUS_NOT_IMPLEMENTED;
682 IoStatusBlock->Information = 0;
683 if (hEvent) NtSetEvent(hEvent, NULL);
685 return IoStatusBlock->u.Status;
688 /******************************************************************************
689 * NtFsControlFile [NTDLL.@]
690 * ZwFsControlFile [NTDLL.@]
692 NTSTATUS WINAPI NtFsControlFile(
693 IN HANDLE DeviceHandle,
694 IN HANDLE Event OPTIONAL,
695 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
696 IN PVOID ApcContext OPTIONAL,
697 OUT PIO_STATUS_BLOCK IoStatusBlock,
698 IN ULONG IoControlCode,
699 IN PVOID InputBuffer,
700 IN ULONG InputBufferSize,
701 OUT PVOID OutputBuffer,
702 IN ULONG OutputBufferSize)
704 FIXME("(%p,%p,%p,%p,%p,0x%08lx,%p,0x%08lx,%p,0x%08lx): stub\n",
705 DeviceHandle,Event,ApcRoutine,ApcContext,IoStatusBlock,IoControlCode,
706 InputBuffer,InputBufferSize,OutputBuffer,OutputBufferSize);
710 /******************************************************************************
711 * NtSetVolumeInformationFile [NTDLL.@]
712 * ZwSetVolumeInformationFile [NTDLL.@]
714 * Set volume information for an open file handle.
717 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
718 * IoStatusBlock [O] Receives information about the operation on return
719 * FsInformation [I] Source for volume information
720 * Length [I] Size of FsInformation
721 * FsInformationClass [I] Type of volume information to set
724 * Success: 0. IoStatusBlock is updated.
725 * Failure: An NTSTATUS error code describing the error.
727 NTSTATUS WINAPI NtSetVolumeInformationFile(
728 IN HANDLE FileHandle,
729 PIO_STATUS_BLOCK IoStatusBlock,
732 FS_INFORMATION_CLASS FsInformationClass)
734 FIXME("(%p,%p,%p,0x%08lx,0x%08x) stub\n",
735 FileHandle,IoStatusBlock,FsInformation,Length,FsInformationClass);
739 /******************************************************************************
740 * NtQueryInformationFile [NTDLL.@]
741 * ZwQueryInformationFile [NTDLL.@]
743 * Get information about an open file handle.
746 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
747 * IoStatusBlock [O] Receives information about the operation on return
748 * FileInformation [O] Destination for file information
749 * Length [I] Size of FileInformation
750 * FileInformationClass [I] Type of file information to get
753 * Success: 0. IoStatusBlock and FileInformation are updated.
754 * Failure: An NTSTATUS error code describing the error.
756 NTSTATUS WINAPI NtQueryInformationFile(HANDLE hFile, PIO_STATUS_BLOCK io_status,
758 FILE_INFORMATION_CLASS class)
763 time_t ct = 0, wt = 0, at = 0;
765 TRACE("(%p,%p,%p,0x%08lx,0x%08x)\n", hFile, io_status, ptr, len, class);
769 case FileBasicInformation:
771 FILE_BASIC_INFORMATION* fbi = (FILE_BASIC_INFORMATION*)answer;
772 if (sizeof(answer) < sizeof(*fbi)) goto too_small;
774 SERVER_START_REQ( get_file_info )
777 if (!(status = wine_server_call( req )))
779 /* FIXME: which file types are supported ?
780 * Serial ports (FILE_TYPE_CHAR) are not,
781 * and MSDN also says that pipes are not supported.
782 * FILE_TYPE_REMOTE seems to be supported according to
783 * MSDN q234741.txt */
784 if ((reply->type == FILE_TYPE_DISK) ||
785 (reply->type == FILE_TYPE_REMOTE))
787 at = reply->access_time;
788 wt = reply->write_time;
789 ct = reply->change_time;
790 fbi->FileAttributes = reply->attr;
793 else status = STATUS_INVALID_HANDLE; /* FIXME ??? */
799 RtlSecondsSince1970ToTime(wt, &fbi->CreationTime);
800 RtlSecondsSince1970ToTime(wt, &fbi->LastWriteTime);
801 RtlSecondsSince1970ToTime(ct, &fbi->ChangeTime);
802 RtlSecondsSince1970ToTime(at, &fbi->LastAccessTime);
806 case FileStandardInformation:
808 FILE_STANDARD_INFORMATION* fsi = (FILE_STANDARD_INFORMATION*)answer;
809 if (sizeof(answer) < sizeof(*fsi)) goto too_small;
811 SERVER_START_REQ( get_file_info )
814 if (!(status = wine_server_call( req )))
816 /* FIXME: which file types are supported ?
817 * Serial ports (FILE_TYPE_CHAR) are not,
818 * and MSDN also says that pipes are not supported.
819 * FILE_TYPE_REMOTE seems to be supported according to
820 * MSDN q234741.txt */
821 if ((reply->type == FILE_TYPE_DISK) ||
822 (reply->type == FILE_TYPE_REMOTE))
824 fsi->AllocationSize.u.HighPart = reply->alloc_high;
825 fsi->AllocationSize.u.LowPart = reply->alloc_low;
826 fsi->EndOfFile.u.HighPart = reply->size_high;
827 fsi->EndOfFile.u.LowPart = reply->size_low;
828 fsi->NumberOfLinks = reply->links;
829 fsi->DeletePending = FALSE; /* FIXME */
830 fsi->Directory = (reply->attr & FILE_ATTRIBUTE_DIRECTORY);
833 else status = STATUS_INVALID_HANDLE; /* FIXME ??? */
839 case FilePositionInformation:
841 FILE_POSITION_INFORMATION* fpi = (FILE_POSITION_INFORMATION*)answer;
842 if (sizeof(answer) < sizeof(*fpi)) goto too_small;
844 SERVER_START_REQ( set_file_pointer )
849 req->whence = SEEK_CUR;
850 if (!(status = wine_server_call( req )))
852 fpi->CurrentByteOffset.u.HighPart = reply->new_high;
853 fpi->CurrentByteOffset.u.LowPart = reply->new_low;
861 FIXME("Unsupported class (%d)\n", class);
862 return io_status->u.Status = STATUS_NOT_IMPLEMENTED;
864 if (used) memcpy(ptr, answer, min(used, len));
865 io_status->u.Status = status;
866 io_status->Information = len;
869 io_status->Information = 0;
870 return io_status->u.Status = STATUS_BUFFER_TOO_SMALL;
873 /******************************************************************************
874 * NtSetInformationFile [NTDLL.@]
875 * ZwSetInformationFile [NTDLL.@]
877 * Set information about an open file handle.
880 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
881 * IoStatusBlock [O] Receives information about the operation on return
882 * FileInformation [I] Source for file information
883 * Length [I] Size of FileInformation
884 * FileInformationClass [I] Type of file information to set
887 * Success: 0. IoStatusBlock is updated.
888 * Failure: An NTSTATUS error code describing the error.
890 NTSTATUS WINAPI NtSetInformationFile(HANDLE hFile, PIO_STATUS_BLOCK io_status,
891 PVOID ptr, ULONG len,
892 FILE_INFORMATION_CLASS class)
894 NTSTATUS status = STATUS_INVALID_PARAMETER_3;
896 TRACE("(%p,%p,%p,0x%08lx,0x%08x)\n", hFile, io_status, ptr, len, class);
900 case FilePositionInformation:
901 if (len >= sizeof(FILE_POSITION_INFORMATION))
903 FILE_POSITION_INFORMATION* fpi = (FILE_POSITION_INFORMATION*)ptr;
905 SERVER_START_REQ( set_file_pointer )
908 req->low = fpi->CurrentByteOffset.u.LowPart;
909 req->high = fpi->CurrentByteOffset.u.HighPart;
910 req->whence = SEEK_SET;
911 status = wine_server_call( req );
914 status = STATUS_SUCCESS;
918 FIXME("Unsupported class (%d)\n", class);
919 return STATUS_NOT_IMPLEMENTED;
921 io_status->u.Status = status;
922 io_status->Information = 0;
926 /******************************************************************************
927 * NtQueryVolumeInformationFile [NTDLL.@]
928 * ZwQueryVolumeInformationFile [NTDLL.@]
930 * Get volume information for an open file handle.
933 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
934 * IoStatusBlock [O] Receives information about the operation on return
935 * FsInformation [O] Destination for volume information
936 * Length [I] Size of FsInformation
937 * FsInformationClass [I] Type of volume information to set
940 * Success: 0. IoStatusBlock and FsInformation are updated.
941 * Failure: An NTSTATUS error code describing the error.
943 NTSTATUS WINAPI NtQueryVolumeInformationFile (
944 IN HANDLE FileHandle,
945 OUT PIO_STATUS_BLOCK IoStatusBlock,
946 OUT PVOID FSInformation,
948 IN FS_INFORMATION_CLASS FSInformationClass)
952 FIXME("(%p %p %p 0x%08lx 0x%08x) stub!\n",
953 FileHandle, IoStatusBlock, FSInformation, Length, FSInformationClass);
955 switch ( FSInformationClass )
957 case FileFsVolumeInformation:
958 len = sizeof( FILE_FS_VOLUME_INFORMATION );
960 case FileFsLabelInformation:
964 case FileFsSizeInformation:
965 len = sizeof( FILE_FS_SIZE_INFORMATION );
968 case FileFsDeviceInformation:
969 len = sizeof( FILE_FS_DEVICE_INFORMATION );
971 case FileFsAttributeInformation:
972 len = sizeof( FILE_FS_ATTRIBUTE_INFORMATION );
975 case FileFsControlInformation:
979 case FileFsFullSizeInformation:
983 case FileFsObjectIdInformation:
987 case FileFsMaximumInformation:
993 return STATUS_BUFFER_TOO_SMALL;
995 switch ( FSInformationClass )
997 case FileFsVolumeInformation:
999 case FileFsLabelInformation:
1002 case FileFsSizeInformation:
1005 case FileFsDeviceInformation:
1008 FILE_FS_DEVICE_INFORMATION * DeviceInfo = FSInformation;
1009 DeviceInfo->DeviceType = FILE_DEVICE_DISK;
1010 DeviceInfo->Characteristics = 0;
1013 case FileFsAttributeInformation:
1016 case FileFsControlInformation:
1019 case FileFsFullSizeInformation:
1022 case FileFsObjectIdInformation:
1025 case FileFsMaximumInformation:
1028 IoStatusBlock->u.Status = STATUS_SUCCESS;
1029 IoStatusBlock->Information = len;
1030 return STATUS_SUCCESS;
1033 /******************************************************************
1034 * NtFlushBuffersFile (NTDLL.@)
1036 * Flush any buffered data on an open file handle.
1039 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
1040 * IoStatusBlock [O] Receives information about the operation on return
1043 * Success: 0. IoStatusBlock is updated.
1044 * Failure: An NTSTATUS error code describing the error.
1046 NTSTATUS WINAPI NtFlushBuffersFile( HANDLE hFile, IO_STATUS_BLOCK* IoStatusBlock )
1049 HANDLE hEvent = NULL;
1051 SERVER_START_REQ( flush_file )
1053 req->handle = hFile;
1054 ret = wine_server_call( req );
1055 hEvent = reply->event;
1060 ret = NtWaitForSingleObject( hEvent, FALSE, NULL );
1066 /******************************************************************
1067 * NtLockFile (NTDLL.@)
1071 NTSTATUS WINAPI NtLockFile( HANDLE hFile, HANDLE lock_granted_event,
1072 PIO_APC_ROUTINE apc, void* apc_user,
1073 PIO_STATUS_BLOCK io_status, PLARGE_INTEGER offset,
1074 PLARGE_INTEGER count, ULONG* key, BOOLEAN dont_wait,
1081 if (apc || io_status || key)
1083 FIXME("Unimplemented yet parameter\n");
1084 return STATUS_NOT_IMPLEMENTED;
1089 SERVER_START_REQ( lock_file )
1091 req->handle = hFile;
1092 req->offset_low = offset->u.LowPart;
1093 req->offset_high = offset->u.HighPart;
1094 req->count_low = count->u.LowPart;
1095 req->count_high = count->u.HighPart;
1096 req->shared = !exclusive;
1097 req->wait = !dont_wait;
1098 ret = wine_server_call( req );
1099 handle = reply->handle;
1100 async = reply->overlapped;
1103 if (ret != STATUS_PENDING)
1105 if (!ret && lock_granted_event) NtSetEvent(lock_granted_event, NULL);
1111 FIXME( "Async I/O lock wait not implemented, might deadlock\n" );
1112 if (handle) NtClose( handle );
1113 return STATUS_PENDING;
1117 NtWaitForSingleObject( handle, FALSE, NULL );
1124 /* Unix lock conflict, sleep a bit and retry */
1125 time.QuadPart = 100 * (ULONGLONG)10000;
1126 time.QuadPart = -time.QuadPart;
1127 NtDelayExecution( FALSE, &time );
1133 /******************************************************************
1134 * NtUnlockFile (NTDLL.@)
1138 NTSTATUS WINAPI NtUnlockFile( HANDLE hFile, PIO_STATUS_BLOCK io_status,
1139 PLARGE_INTEGER offset, PLARGE_INTEGER count,
1144 TRACE( "%p %lx%08lx %lx%08lx\n",
1145 hFile, offset->u.HighPart, offset->u.LowPart, count->u.HighPart, count->u.LowPart );
1147 if (io_status || key)
1149 FIXME("Unimplemented yet parameter\n");
1150 return STATUS_NOT_IMPLEMENTED;
1153 SERVER_START_REQ( unlock_file )
1155 req->handle = hFile;
1156 req->offset_low = offset->u.LowPart;
1157 req->offset_high = offset->u.HighPart;
1158 req->count_low = count->u.LowPart;
1159 req->count_high = count->u.HighPart;
1160 status = wine_server_call( req );