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 * FileHandle [O] Variable that receives the file handle on return
75 * DesiredAccess [I] Access desired by the caller to the file
76 * ObjectAttributes [I] Structue describing the file to be opened
77 * IoStatusBlock [O] Receives details about the result of the operation
78 * ShareAccess [I] Type of shared access the caller requires
79 * OpenOptions [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(
86 OUT PHANDLE FileHandle
,
87 ACCESS_MASK DesiredAccess
,
88 POBJECT_ATTRIBUTES ObjectAttributes
,
89 OUT PIO_STATUS_BLOCK IoStatusBlock
,
94 static const WCHAR szDosDevices
[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\',0};
96 FIXME("(%p,0x%08lx,%p,%p,0x%08lx,0x%08lx) partial stub\n",
97 FileHandle
, DesiredAccess
, ObjectAttributes
,
98 IoStatusBlock
, ShareAccess
, OpenOptions
);
100 dump_ObjectAttributes (ObjectAttributes
);
102 if(ObjectAttributes
->RootDirectory
)
104 FIXME("Object root directory unknown %p\n",
105 ObjectAttributes
->RootDirectory
);
106 return STATUS_OBJECT_NAME_NOT_FOUND
;
109 filename
= ObjectAttributes
->ObjectName
->Buffer
;
111 /* FIXME: DOSFS stuff should call here, not vice-versa */
112 if(strncmpW(filename
, szDosDevices
, strlenW(szDosDevices
)))
113 return STATUS_OBJECT_NAME_NOT_FOUND
;
115 /* FIXME: this calls SetLastError() -> bad */
116 *FileHandle
= pCreateFileW( &filename
[strlenW(szDosDevices
)], DesiredAccess
, ShareAccess
,
117 NULL
, OPEN_EXISTING
, 0, 0 );
118 if (*FileHandle
== INVALID_HANDLE_VALUE
) return STATUS_OBJECT_NAME_NOT_FOUND
;
119 return STATUS_SUCCESS
;
122 /**************************************************************************
123 * NtCreateFile [NTDLL.@]
124 * ZwCreateFile [NTDLL.@]
126 * Either create a new file or directory, or open an existing file, device,
127 * directory or volume.
130 * FileHandle [O] Points to a variable which receives the file handle on return
131 * DesiredAccess [I] Desired access to the file
132 * ObjectAttributes [I] Structure describing the file
133 * IoStatusBlock [O] Receives information about the operation on return
134 * AllocationSize [I] Initial size of the file in bytes
135 * FileAttributes [I] Attributes to create the file with
136 * ShareAccess [I] Type of shared access the caller would like to the file
137 * CreateDisposition [I] Specifies what to do, depending on whether the file already exists
138 * CreateOptions [I] Options for creating a new file
139 * EaBuffer [I] Undocumented
140 * EaLength [I] Undocumented
143 * Success: 0. FileHandle and IoStatusBlock are updated.
144 * Failure: An NTSTATUS error code describing the error.
146 NTSTATUS WINAPI
NtCreateFile(
147 OUT PHANDLE FileHandle
,
148 ACCESS_MASK DesiredAccess
,
149 POBJECT_ATTRIBUTES ObjectAttributes
,
150 OUT PIO_STATUS_BLOCK IoStatusBlock
,
151 PLARGE_INTEGER AllocateSize
,
152 ULONG FileAttributes
,
154 ULONG CreateDisposition
,
159 FIXME("(%p,0x%08lx,%p,%p,%p,0x%08lx,0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx) stub\n",
160 FileHandle
,DesiredAccess
,ObjectAttributes
,
161 IoStatusBlock
,AllocateSize
,FileAttributes
,
162 ShareAccess
,CreateDisposition
,CreateOptions
,EaBuffer
,EaLength
);
163 dump_ObjectAttributes (ObjectAttributes
);
167 /***********************************************************************
168 * Asynchronous file I/O *
170 static DWORD
fileio_get_async_count(const async_private
*ovp
);
171 static void CALLBACK
fileio_call_completion_func(ULONG_PTR data
);
172 static void fileio_async_cleanup(async_private
*ovp
);
174 static async_ops fileio_async_ops
=
176 fileio_get_async_count
, /* get_count */
177 fileio_call_completion_func
, /* call_completion */
178 fileio_async_cleanup
/* cleanup */
181 static async_ops fileio_nocomp_async_ops
=
183 fileio_get_async_count
, /* get_count */
184 NULL
, /* call_completion */
185 fileio_async_cleanup
/* cleanup */
188 typedef struct async_fileio
190 struct async_private async
;
195 unsigned long offset
;
196 enum fd_type fd_type
;
199 static DWORD
fileio_get_async_count(const struct async_private
*ovp
)
201 async_fileio
*fileio
= (async_fileio
*) ovp
;
203 if (fileio
->count
< fileio
->async
.iosb
->Information
)
205 return fileio
->count
- fileio
->async
.iosb
->Information
;
208 static void CALLBACK
fileio_call_completion_func(ULONG_PTR data
)
210 async_fileio
*ovp
= (async_fileio
*) data
;
211 TRACE("data: %p\n", ovp
);
213 ovp
->apc( ovp
->apc_user
, ovp
->async
.iosb
, ovp
->async
.iosb
->Information
);
215 fileio_async_cleanup( &ovp
->async
);
218 static void fileio_async_cleanup( struct async_private
*ovp
)
220 RtlFreeHeap( GetProcessHeap(), 0, ovp
);
223 /***********************************************************************
224 * FILE_GetNtStatus(void)
226 * Retrieve the Nt Status code from errno.
227 * Try to be consistent with FILE_SetDosError().
229 NTSTATUS
FILE_GetNtStatus(void)
234 TRACE( "errno = %d\n", errno
);
237 case EAGAIN
: nt
= STATUS_SHARING_VIOLATION
; break;
238 case EBADF
: nt
= STATUS_INVALID_HANDLE
; break;
239 case ENOSPC
: nt
= STATUS_DISK_FULL
; break;
242 case EACCES
: nt
= STATUS_ACCESS_DENIED
; break;
243 case ENOENT
: nt
= STATUS_SHARING_VIOLATION
; break;
244 case EISDIR
: nt
= STATUS_FILE_IS_A_DIRECTORY
; break;
246 case ENFILE
: nt
= STATUS_NO_MORE_FILES
; break;
248 case ENOTEMPTY
: nt
= STATUS_DIRECTORY_NOT_EMPTY
; break;
249 case EPIPE
: nt
= STATUS_PIPE_BROKEN
; break;
250 case EIO
: nt
= STATUS_DEVICE_NOT_READY
; break;
251 case ENOEXEC
: /* ?? */
252 case ESPIPE
: /* ?? */
253 case EEXIST
: /* ?? */
255 FIXME( "Converting errno %d to STATUS_UNSUCCESSFUL\n", err
);
256 nt
= STATUS_UNSUCCESSFUL
;
261 /***********************************************************************
262 * FILE_AsyncReadService (INTERNAL)
264 * This function is called while the client is waiting on the
265 * server, so we can't make any server calls here.
267 static void FILE_AsyncReadService(async_private
*ovp
)
269 async_fileio
*fileio
= (async_fileio
*) ovp
;
270 IO_STATUS_BLOCK
* io_status
= fileio
->async
.iosb
;
272 int already
= io_status
->Information
;
274 TRACE("%p %p\n", io_status
, fileio
->buffer
);
276 /* check to see if the data is ready (non-blocking) */
278 if ( fileio
->fd_type
== FD_TYPE_SOCKET
)
279 result
= read(ovp
->fd
, &fileio
->buffer
[already
], fileio
->count
- already
);
282 result
= pread(ovp
->fd
, &fileio
->buffer
[already
], fileio
->count
- already
,
283 fileio
->offset
+ already
);
284 if ((result
< 0) && (errno
== ESPIPE
))
285 result
= read(ovp
->fd
, &fileio
->buffer
[already
], fileio
->count
- already
);
288 if ((result
< 0) && ((errno
== EAGAIN
) || (errno
== EINTR
)))
290 TRACE("Deferred read %d\n",errno
);
291 io_status
->u
.Status
= STATUS_PENDING
;
295 /* check to see if the transfer is complete */
298 io_status
->u
.Status
= FILE_GetNtStatus();
301 else if (result
== 0)
303 io_status
->u
.Status
= io_status
->Information
? STATUS_SUCCESS
: STATUS_END_OF_FILE
;
307 io_status
->Information
+= result
;
308 if (io_status
->Information
>= fileio
->count
|| fileio
->fd_type
== FD_TYPE_SOCKET
)
309 io_status
->u
.Status
= STATUS_SUCCESS
;
311 io_status
->u
.Status
= STATUS_PENDING
;
313 TRACE("read %d more bytes %ld/%d so far\n",
314 result
, io_status
->Information
, fileio
->count
);
318 /******************************************************************************
319 * NtReadFile [NTDLL.@]
320 * ZwReadFile [NTDLL.@]
322 * Read from an open file handle.
325 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
326 * Event [I] Event to signal upon completion (or NULL)
327 * ApcRoutine [I] Callback to call upon completion (or NULL)
328 * ApcContext [I] Context for ApcRoutine (or NULL)
329 * IoStatusBlock [O] Receives information about the operation on return
330 * Buffer [O] Destination for the data read
331 * Length [I] Size of Buffer
332 * ByteOffset [O] Destination for the new file pointer position (or NULL)
333 * Key [O] Function unknown (may be NULL)
336 * Success: 0. IoStatusBlock is updated, and the Information member contains
337 * The number of bytes read.
338 * Failure: An NTSTATUS error code describing the error.
340 NTSTATUS WINAPI
NtReadFile(HANDLE hFile
, HANDLE hEvent
,
341 PIO_APC_ROUTINE apc
, void* apc_user
,
342 PIO_STATUS_BLOCK io_status
, void* buffer
, ULONG length
,
343 PLARGE_INTEGER offset
, PULONG key
)
345 int unix_handle
, flags
;
348 TRACE("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%p),partial stub!\n",
349 hFile
,hEvent
,apc
,apc_user
,io_status
,buffer
,length
,offset
,key
);
351 io_status
->Information
= 0;
352 io_status
->u
.Status
= wine_server_handle_to_fd( hFile
, GENERIC_READ
, &unix_handle
, &type
, &flags
);
353 if (io_status
->u
.Status
) return io_status
->u
.Status
;
355 if (flags
& FD_FLAG_RECV_SHUTDOWN
)
357 wine_server_release_fd( hFile
, unix_handle
);
358 return STATUS_PIPE_DISCONNECTED
;
361 if (flags
& FD_FLAG_TIMEOUT
)
365 /* this shouldn't happen, but check it */
366 FIXME("NIY-hEvent\n");
367 wine_server_release_fd( hFile
, unix_handle
);
368 return STATUS_NOT_IMPLEMENTED
;
370 io_status
->u
.Status
= NtCreateEvent(&hEvent
, SYNCHRONIZE
, NULL
, 0, 0);
371 if (io_status
->u
.Status
)
373 wine_server_release_fd( hFile
, unix_handle
);
374 return io_status
->u
.Status
;
378 if (flags
& (FD_FLAG_OVERLAPPED
|FD_FLAG_TIMEOUT
))
383 if (!(ovp
= RtlAllocateHeap(GetProcessHeap(), 0, sizeof(async_fileio
))))
385 wine_server_release_fd( hFile
, unix_handle
);
386 return STATUS_NO_MEMORY
;
388 ovp
->async
.ops
= (apc
? &fileio_async_ops
: &fileio_nocomp_async_ops
);
389 ovp
->async
.handle
= hFile
;
390 ovp
->async
.fd
= unix_handle
; /* FIXME */
391 ovp
->async
.type
= ASYNC_TYPE_READ
;
392 ovp
->async
.func
= FILE_AsyncReadService
;
393 ovp
->async
.event
= hEvent
;
394 ovp
->async
.iosb
= io_status
;
396 if ( offset
== NULL
)
400 ovp
->offset
= offset
->u
.LowPart
;
401 if (offset
->u
.HighPart
) FIXME("NIY-high part\n");
404 ovp
->apc_user
= apc_user
;
405 ovp
->buffer
= buffer
;
408 io_status
->Information
= 0;
409 ret
= register_new_async(&ovp
->async
);
410 if (ret
!= STATUS_SUCCESS
)
412 if (flags
& FD_FLAG_TIMEOUT
)
414 NtWaitForSingleObject(hEvent
, TRUE
, NULL
);
419 LARGE_INTEGER timeout
;
421 /* let some APC be run, this will read some already pending data */
422 timeout
.u
.LowPart
= timeout
.u
.HighPart
= 0;
423 NtDelayExecution( TRUE
, &timeout
);
425 return io_status
->u
.Status
;
432 /* return SMB_ReadFile(hFile, unix_handle, buffer, length, io_status); */
433 wine_server_release_fd( hFile
, unix_handle
);
434 return STATUS_INVALID_HANDLE
;
436 case FD_TYPE_DEFAULT
:
437 /* normal unix file */
441 FIXME("Unsupported type of fd %d\n", type
);
442 wine_server_release_fd( hFile
, unix_handle
);
443 return STATUS_INVALID_HANDLE
;
448 FILE_POSITION_INFORMATION fpi
;
450 fpi
.CurrentByteOffset
= *offset
;
451 io_status
->u
.Status
= NtSetInformationFile(hFile
, io_status
, &fpi
, sizeof(fpi
),
452 FilePositionInformation
);
453 if (io_status
->u
.Status
)
455 wine_server_release_fd( hFile
, unix_handle
);
456 return io_status
->u
.Status
;
459 /* code for synchronous reads */
460 while ((io_status
->Information
= read( unix_handle
, buffer
, length
)) == -1)
462 if ((errno
== EAGAIN
) || (errno
== EINTR
)) continue;
463 if (errno
== EFAULT
) FIXME( "EFAULT handling broken for now\n" );
464 io_status
->u
.Status
= FILE_GetNtStatus();
467 wine_server_release_fd( hFile
, unix_handle
);
468 return io_status
->u
.Status
;
471 /***********************************************************************
472 * FILE_AsyncWriteService (INTERNAL)
474 * This function is called while the client is waiting on the
475 * server, so we can't make any server calls here.
477 static void FILE_AsyncWriteService(struct async_private
*ovp
)
479 async_fileio
*fileio
= (async_fileio
*) ovp
;
480 PIO_STATUS_BLOCK io_status
= fileio
->async
.iosb
;
482 int already
= io_status
->Information
;
484 TRACE("(%p %p)\n",io_status
,fileio
->buffer
);
486 /* write some data (non-blocking) */
488 if ( fileio
->fd_type
== FD_TYPE_SOCKET
)
489 result
= write(ovp
->fd
, &fileio
->buffer
[already
], fileio
->count
- already
);
492 result
= pwrite(ovp
->fd
, &fileio
->buffer
[already
], fileio
->count
- already
,
493 fileio
->offset
+ already
);
494 if ((result
< 0) && (errno
== ESPIPE
))
495 result
= write(ovp
->fd
, &fileio
->buffer
[already
], fileio
->count
- already
);
498 if ((result
< 0) && ((errno
== EAGAIN
) || (errno
== EINTR
)))
500 io_status
->u
.Status
= STATUS_PENDING
;
504 /* check to see if the transfer is complete */
507 io_status
->u
.Status
= FILE_GetNtStatus();
511 io_status
->Information
+= result
;
512 io_status
->u
.Status
= (io_status
->Information
< fileio
->count
) ? STATUS_PENDING
: STATUS_SUCCESS
;
513 TRACE("wrote %d more bytes %ld/%d so far\n",result
,io_status
->Information
,fileio
->count
);
516 /******************************************************************************
517 * NtWriteFile [NTDLL.@]
518 * ZwWriteFile [NTDLL.@]
520 * Write to an open file handle.
523 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
524 * Event [I] Event to signal upon completion (or NULL)
525 * ApcRoutine [I] Callback to call upon completion (or NULL)
526 * ApcContext [I] Context for ApcRoutine (or NULL)
527 * IoStatusBlock [O] Receives information about the operation on return
528 * Buffer [I] Source for the data to write
529 * Length [I] Size of Buffer
530 * ByteOffset [O] Destination for the new file pointer position (or NULL)
531 * Key [O] Function unknown (may be NULL)
534 * Success: 0. IoStatusBlock is updated, and the Information member contains
535 * The number of bytes written.
536 * Failure: An NTSTATUS error code describing the error.
538 NTSTATUS WINAPI
NtWriteFile(HANDLE hFile
, HANDLE hEvent
,
539 PIO_APC_ROUTINE apc
, void* apc_user
,
540 PIO_STATUS_BLOCK io_status
,
541 const void* buffer
, ULONG length
,
542 PLARGE_INTEGER offset
, PULONG key
)
544 int unix_handle
, flags
;
547 TRACE("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%p)!\n",
548 hFile
,hEvent
,apc
,apc_user
,io_status
,buffer
,length
,offset
,key
);
550 TRACE("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%p),partial stub!\n",
551 hFile
,hEvent
,apc
,apc_user
,io_status
,buffer
,length
,offset
,key
);
553 io_status
->Information
= 0;
554 io_status
->u
.Status
= wine_server_handle_to_fd( hFile
, GENERIC_WRITE
, &unix_handle
, &type
, &flags
);
555 if (io_status
->u
.Status
) return io_status
->u
.Status
;
557 if (flags
& FD_FLAG_SEND_SHUTDOWN
)
559 wine_server_release_fd( hFile
, unix_handle
);
560 return STATUS_PIPE_DISCONNECTED
;
563 if (flags
& (FD_FLAG_OVERLAPPED
|FD_FLAG_TIMEOUT
))
568 if (!(ovp
= RtlAllocateHeap(GetProcessHeap(), 0, sizeof(async_fileio
))))
570 wine_server_release_fd( hFile
, unix_handle
);
571 return STATUS_NO_MEMORY
;
573 ovp
->async
.ops
= (apc
? &fileio_async_ops
: &fileio_nocomp_async_ops
);
574 ovp
->async
.handle
= hFile
;
575 ovp
->async
.fd
= unix_handle
; /* FIXME */
576 ovp
->async
.type
= ASYNC_TYPE_WRITE
;
577 ovp
->async
.func
= FILE_AsyncWriteService
;
578 ovp
->async
.event
= hEvent
;
579 ovp
->async
.iosb
= io_status
;
582 ovp
->offset
= offset
->u
.LowPart
;
583 if (offset
->u
.HighPart
) FIXME("NIY-high part\n");
588 ovp
->apc_user
= apc_user
;
589 ovp
->buffer
= (void*)buffer
;
592 io_status
->Information
= 0;
593 ret
= register_new_async(&ovp
->async
);
594 if (ret
!= STATUS_SUCCESS
)
596 if (flags
& FD_FLAG_TIMEOUT
)
598 NtWaitForSingleObject(hEvent
, TRUE
, NULL
);
603 LARGE_INTEGER timeout
;
605 /* let some APC be run, this will write as much data as possible */
606 timeout
.u
.LowPart
= timeout
.u
.HighPart
= 0;
607 NtDelayExecution( TRUE
, &timeout
);
609 return io_status
->u
.Status
;
615 wine_server_release_fd( hFile
, unix_handle
);
616 return STATUS_NOT_IMPLEMENTED
;
618 case FD_TYPE_DEFAULT
:
619 /* normal unix files */
620 if (unix_handle
== -1) return STATUS_INVALID_HANDLE
;
624 FIXME("Unsupported type of fd %d\n", type
);
625 wine_server_release_fd( hFile
, unix_handle
);
626 return STATUS_INVALID_HANDLE
;
631 FILE_POSITION_INFORMATION fpi
;
633 fpi
.CurrentByteOffset
= *offset
;
634 io_status
->u
.Status
= NtSetInformationFile(hFile
, io_status
, &fpi
, sizeof(fpi
),
635 FilePositionInformation
);
636 if (io_status
->u
.Status
)
638 wine_server_release_fd( hFile
, unix_handle
);
639 return io_status
->u
.Status
;
643 /* synchronous file write */
644 while ((io_status
->Information
= write( unix_handle
, buffer
, length
)) == -1)
646 if ((errno
== EAGAIN
) || (errno
== EINTR
)) continue;
647 if (errno
== EFAULT
) FIXME( "EFAULT handling broken for now\n" );
648 if (errno
== ENOSPC
) io_status
->u
.Status
= STATUS_DISK_FULL
;
649 else io_status
->u
.Status
= FILE_GetNtStatus();
652 wine_server_release_fd( hFile
, unix_handle
);
653 return io_status
->u
.Status
;
656 /**************************************************************************
657 * NtDeviceIoControlFile [NTDLL.@]
658 * ZwDeviceIoControlFile [NTDLL.@]
660 * Perform an I/O control operation on an open file handle.
663 * DeviceHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
664 * Event [I] Event to signal upon completion (or NULL)
665 * ApcRoutine [I] Callback to call upon completion (or NULL)
666 * ApcContext [I] Context for ApcRoutine (or NULL)
667 * IoStatusBlock [O] Receives information about the operation on return
668 * IoControlCode [I] Control code for the operation to perform
669 * InputBuffer [I] Source for any input data required (or NULL)
670 * InputBufferSize [I] Size of InputBuffer
671 * OutputBuffer [O] Source for any output data returned (or NULL)
672 * OutputBufferSize [I] Size of OutputBuffer
675 * Success: 0. IoStatusBlock is updated.
676 * Failure: An NTSTATUS error code describing the error.
678 NTSTATUS WINAPI
NtDeviceIoControlFile(HANDLE DeviceHandle
, HANDLE hEvent
,
679 PIO_APC_ROUTINE UserApcRoutine
,
680 PVOID UserApcContext
,
681 PIO_STATUS_BLOCK IoStatusBlock
,
684 ULONG InputBufferSize
,
686 ULONG OutputBufferSize
)
688 TRACE("(%p,%p,%p,%p,%p,0x%08lx,%p,0x%08lx,%p,0x%08lx)\n",
689 DeviceHandle
, hEvent
, UserApcRoutine
, UserApcContext
,
690 IoStatusBlock
, IoControlCode
,
691 InputBuffer
, InputBufferSize
, OutputBuffer
, OutputBufferSize
);
693 if (CDROM_DeviceIoControl(DeviceHandle
, hEvent
,
694 UserApcRoutine
, UserApcContext
,
695 IoStatusBlock
, IoControlCode
,
696 InputBuffer
, InputBufferSize
,
697 OutputBuffer
, OutputBufferSize
) == STATUS_NO_SUCH_DEVICE
)
699 /* it wasn't a CDROM */
700 FIXME("Unimplemented dwIoControlCode=%08lx\n", IoControlCode
);
701 IoStatusBlock
->u
.Status
= STATUS_NOT_IMPLEMENTED
;
702 IoStatusBlock
->Information
= 0;
703 if (hEvent
) NtSetEvent(hEvent
, NULL
);
705 return IoStatusBlock
->u
.Status
;
708 /******************************************************************************
709 * NtFsControlFile [NTDLL.@]
710 * ZwFsControlFile [NTDLL.@]
712 NTSTATUS WINAPI
NtFsControlFile(
713 IN HANDLE DeviceHandle
,
714 IN HANDLE Event OPTIONAL
,
715 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
716 IN PVOID ApcContext OPTIONAL
,
717 OUT PIO_STATUS_BLOCK IoStatusBlock
,
718 IN ULONG IoControlCode
,
719 IN PVOID InputBuffer
,
720 IN ULONG InputBufferSize
,
721 OUT PVOID OutputBuffer
,
722 IN ULONG OutputBufferSize
)
724 FIXME("(%p,%p,%p,%p,%p,0x%08lx,%p,0x%08lx,%p,0x%08lx): stub\n",
725 DeviceHandle
,Event
,ApcRoutine
,ApcContext
,IoStatusBlock
,IoControlCode
,
726 InputBuffer
,InputBufferSize
,OutputBuffer
,OutputBufferSize
);
730 /******************************************************************************
731 * NtSetVolumeInformationFile [NTDLL.@]
732 * ZwSetVolumeInformationFile [NTDLL.@]
734 * Set volume information for an open file handle.
737 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
738 * IoStatusBlock [O] Receives information about the operation on return
739 * FsInformation [I] Source for volume information
740 * Length [I] Size of FsInformation
741 * FsInformationClass [I] Type of volume information to set
744 * Success: 0. IoStatusBlock is updated.
745 * Failure: An NTSTATUS error code describing the error.
747 NTSTATUS WINAPI
NtSetVolumeInformationFile(
748 IN HANDLE FileHandle
,
749 PIO_STATUS_BLOCK IoStatusBlock
,
752 FS_INFORMATION_CLASS FsInformationClass
)
754 FIXME("(%p,%p,%p,0x%08lx,0x%08x) stub\n",
755 FileHandle
,IoStatusBlock
,FsInformation
,Length
,FsInformationClass
);
759 /******************************************************************************
760 * NtQueryInformationFile [NTDLL.@]
761 * ZwQueryInformationFile [NTDLL.@]
763 * Get information about an open file handle.
766 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
767 * IoStatusBlock [O] Receives information about the operation on return
768 * FileInformation [O] Destination for file information
769 * Length [I] Size of FileInformation
770 * FileInformationClass [I] Type of file information to get
773 * Success: 0. IoStatusBlock and FileInformation are updated.
774 * Failure: An NTSTATUS error code describing the error.
776 NTSTATUS WINAPI
NtQueryInformationFile(HANDLE hFile
, PIO_STATUS_BLOCK io_status
,
778 FILE_INFORMATION_CLASS
class)
783 time_t ct
= 0, wt
= 0, at
= 0;
785 TRACE("(%p,%p,%p,0x%08lx,0x%08x)\n", hFile
, io_status
, ptr
, len
, class);
789 case FileBasicInformation
:
791 FILE_BASIC_INFORMATION
* fbi
= (FILE_BASIC_INFORMATION
*)answer
;
792 if (sizeof(answer
) < sizeof(*fbi
)) goto too_small
;
794 SERVER_START_REQ( get_file_info
)
797 if (!(status
= wine_server_call( req
)))
799 /* FIXME: which file types are supported ?
800 * Serial ports (FILE_TYPE_CHAR) are not,
801 * and MSDN also says that pipes are not supported.
802 * FILE_TYPE_REMOTE seems to be supported according to
803 * MSDN q234741.txt */
804 if ((reply
->type
== FILE_TYPE_DISK
) ||
805 (reply
->type
== FILE_TYPE_REMOTE
))
807 at
= reply
->access_time
;
808 wt
= reply
->write_time
;
809 ct
= reply
->change_time
;
810 fbi
->FileAttributes
= reply
->attr
;
813 else status
= STATUS_INVALID_HANDLE
; /* FIXME ??? */
819 RtlSecondsSince1970ToTime(wt
, &fbi
->CreationTime
);
820 RtlSecondsSince1970ToTime(wt
, &fbi
->LastWriteTime
);
821 RtlSecondsSince1970ToTime(ct
, &fbi
->ChangeTime
);
822 RtlSecondsSince1970ToTime(at
, &fbi
->LastAccessTime
);
826 case FileStandardInformation
:
828 FILE_STANDARD_INFORMATION
* fsi
= (FILE_STANDARD_INFORMATION
*)answer
;
829 if (sizeof(answer
) < sizeof(*fsi
)) goto too_small
;
831 SERVER_START_REQ( get_file_info
)
834 if (!(status
= wine_server_call( req
)))
836 /* FIXME: which file types are supported ?
837 * Serial ports (FILE_TYPE_CHAR) are not,
838 * and MSDN also says that pipes are not supported.
839 * FILE_TYPE_REMOTE seems to be supported according to
840 * MSDN q234741.txt */
841 if ((reply
->type
== FILE_TYPE_DISK
) ||
842 (reply
->type
== FILE_TYPE_REMOTE
))
844 fsi
->AllocationSize
.u
.HighPart
= reply
->alloc_high
;
845 fsi
->AllocationSize
.u
.LowPart
= reply
->alloc_low
;
846 fsi
->EndOfFile
.u
.HighPart
= reply
->size_high
;
847 fsi
->EndOfFile
.u
.LowPart
= reply
->size_low
;
848 fsi
->NumberOfLinks
= reply
->links
;
849 fsi
->DeletePending
= FALSE
; /* FIXME */
850 fsi
->Directory
= (reply
->attr
& FILE_ATTRIBUTE_DIRECTORY
);
853 else status
= STATUS_INVALID_HANDLE
; /* FIXME ??? */
859 case FilePositionInformation
:
861 FILE_POSITION_INFORMATION
* fpi
= (FILE_POSITION_INFORMATION
*)answer
;
862 if (sizeof(answer
) < sizeof(*fpi
)) goto too_small
;
864 SERVER_START_REQ( set_file_pointer
)
869 req
->whence
= SEEK_CUR
;
870 if (!(status
= wine_server_call( req
)))
872 fpi
->CurrentByteOffset
.u
.HighPart
= reply
->new_high
;
873 fpi
->CurrentByteOffset
.u
.LowPart
= reply
->new_low
;
881 FIXME("Unsupported class (%d)\n", class);
882 return io_status
->u
.Status
= STATUS_NOT_IMPLEMENTED
;
884 if (used
) memcpy(ptr
, answer
, min(used
, len
));
885 io_status
->u
.Status
= status
;
886 io_status
->Information
= len
;
889 io_status
->Information
= 0;
890 return io_status
->u
.Status
= STATUS_BUFFER_TOO_SMALL
;
893 /******************************************************************************
894 * NtSetInformationFile [NTDLL.@]
895 * ZwSetInformationFile [NTDLL.@]
897 * Set information about an open file handle.
900 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
901 * IoStatusBlock [O] Receives information about the operation on return
902 * FileInformation [I] Source for file information
903 * Length [I] Size of FileInformation
904 * FileInformationClass [I] Type of file information to set
907 * Success: 0. IoStatusBlock is updated.
908 * Failure: An NTSTATUS error code describing the error.
910 NTSTATUS WINAPI
NtSetInformationFile(HANDLE hFile
, PIO_STATUS_BLOCK io_status
,
911 PVOID ptr
, ULONG len
,
912 FILE_INFORMATION_CLASS
class)
914 NTSTATUS status
= STATUS_INVALID_PARAMETER_3
;
916 TRACE("(%p,%p,%p,0x%08lx,0x%08x)\n", hFile
, io_status
, ptr
, len
, class);
920 case FilePositionInformation
:
921 if (len
>= sizeof(FILE_POSITION_INFORMATION
))
923 FILE_POSITION_INFORMATION
* fpi
= (FILE_POSITION_INFORMATION
*)ptr
;
925 SERVER_START_REQ( set_file_pointer
)
928 req
->low
= fpi
->CurrentByteOffset
.u
.LowPart
;
929 req
->high
= fpi
->CurrentByteOffset
.u
.HighPart
;
930 req
->whence
= SEEK_SET
;
931 status
= wine_server_call( req
);
934 status
= STATUS_SUCCESS
;
938 FIXME("Unsupported class (%d)\n", class);
939 return STATUS_NOT_IMPLEMENTED
;
941 io_status
->u
.Status
= status
;
942 io_status
->Information
= 0;
947 /******************************************************************************
948 * NtQueryVolumeInformationFile [NTDLL.@]
949 * ZwQueryVolumeInformationFile [NTDLL.@]
951 * Get volume information for an open file handle.
954 * handle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
955 * io [O] Receives information about the operation on return
956 * buffer [O] Destination for volume information
957 * length [I] Size of FsInformation
958 * info_class [I] Type of volume information to set
961 * Success: 0. io and buffer are updated.
962 * Failure: An NTSTATUS error code describing the error.
964 NTSTATUS WINAPI
NtQueryVolumeInformationFile( HANDLE handle
, PIO_STATUS_BLOCK io
,
965 PVOID buffer
, ULONG length
,
966 FS_INFORMATION_CLASS info_class
)
971 if ((io
->u
.Status
= wine_server_handle_to_fd( handle
, 0, &fd
, NULL
, NULL
)) != STATUS_SUCCESS
)
974 io
->u
.Status
= STATUS_NOT_IMPLEMENTED
;
979 case FileFsVolumeInformation
:
980 FIXME( "%p: volume info not supported\n", handle
);
982 case FileFsLabelInformation
:
983 FIXME( "%p: label info not supported\n", handle
);
985 case FileFsSizeInformation
:
986 if (length
< sizeof(FILE_FS_SIZE_INFORMATION
))
987 io
->u
.Status
= STATUS_BUFFER_TOO_SMALL
;
990 FILE_FS_SIZE_INFORMATION
*info
= buffer
;
991 struct statvfs stvfs
;
993 if (fstat( fd
, &st
) < 0)
995 io
->u
.Status
= FILE_GetNtStatus();
998 if (!S_ISREG(st
.st_mode
) && !S_ISDIR(st
.st_mode
))
1000 io
->u
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
1003 if (fstatvfs( fd
, &stvfs
) < 0) io
->u
.Status
= FILE_GetNtStatus();
1006 info
->TotalAllocationUnits
.QuadPart
= stvfs
.f_blocks
;
1007 info
->AvailableAllocationUnits
.QuadPart
= stvfs
.f_bavail
;
1008 info
->SectorsPerAllocationUnit
= 1;
1009 info
->BytesPerSector
= stvfs
.f_frsize
;
1010 io
->Information
= sizeof(*info
);
1011 io
->u
.Status
= STATUS_SUCCESS
;
1015 case FileFsDeviceInformation
:
1016 if (length
< sizeof(FILE_FS_DEVICE_INFORMATION
))
1017 io
->u
.Status
= STATUS_BUFFER_TOO_SMALL
;
1020 FILE_FS_DEVICE_INFORMATION
*info
= buffer
;
1022 #if defined(linux) && defined(HAVE_FSTATFS)
1025 info
->Characteristics
= 0;
1027 if (fstat( fd
, &st
) < 0)
1029 io
->u
.Status
= FILE_GetNtStatus();
1032 if (S_ISCHR( st
.st_mode
))
1034 switch(major(st
.st_rdev
))
1037 info
->DeviceType
= FILE_DEVICE_NULL
;
1040 info
->DeviceType
= FILE_DEVICE_SERIAL_PORT
;
1043 info
->DeviceType
= FILE_DEVICE_PARALLEL_PORT
;
1046 info
->DeviceType
= FILE_DEVICE_UNKNOWN
;
1050 else if (S_ISBLK( st
.st_mode
))
1052 info
->DeviceType
= FILE_DEVICE_DISK
;
1054 else if (S_ISFIFO( st
.st_mode
) || S_ISSOCK( st
.st_mode
))
1056 info
->DeviceType
= FILE_DEVICE_NAMED_PIPE
;
1058 else /* regular file or directory */
1060 info
->Characteristics
|= FILE_DEVICE_IS_MOUNTED
;
1062 /* check for floppy disk */
1063 if (major(st
.st_dev
) == FLOPPY_MAJOR
)
1064 info
->Characteristics
|= FILE_REMOVABLE_MEDIA
;
1066 if (fstatfs( fd
, &stfs
) < 0) stfs
.f_type
= 0;
1067 switch (stfs
.f_type
)
1069 case 0x9660: /* iso9660 */
1070 case 0x15013346: /* udf */
1071 info
->DeviceType
= FILE_DEVICE_CD_ROM_FILE_SYSTEM
;
1072 info
->Characteristics
|= FILE_REMOVABLE_MEDIA
|FILE_READ_ONLY_DEVICE
;
1074 case 0x6969: /* nfs */
1075 case 0x517B: /* smbfs */
1076 case 0x564c: /* ncpfs */
1077 info
->DeviceType
= FILE_DEVICE_NETWORK_FILE_SYSTEM
;
1078 info
->Characteristics
|= FILE_REMOTE_DEVICE
;
1080 case 0x01021994: /* tmpfs */
1081 case 0x28cd3d45: /* cramfs */
1082 case 0x1373: /* devfs */
1083 case 0x9fa0: /* procfs */
1084 info
->DeviceType
= FILE_DEVICE_VIRTUAL_DISK
;
1087 info
->DeviceType
= FILE_DEVICE_DISK_FILE_SYSTEM
;
1093 if (!warned
++) FIXME( "device info not supported on this platform\n" );
1094 info
->DeviceType
= FILE_DEVICE_DISK_FILE_SYSTEM
;
1095 info
->Characteristics
= 0;
1097 io
->Information
= sizeof(*info
);
1098 io
->u
.Status
= STATUS_SUCCESS
;
1101 case FileFsAttributeInformation
:
1102 FIXME( "%p: attribute info not supported\n", handle
);
1104 case FileFsControlInformation
:
1105 FIXME( "%p: control info not supported\n", handle
);
1107 case FileFsFullSizeInformation
:
1108 FIXME( "%p: full size info not supported\n", handle
);
1110 case FileFsObjectIdInformation
:
1111 FIXME( "%p: object id info not supported\n", handle
);
1113 case FileFsMaximumInformation
:
1114 FIXME( "%p: maximum info not supported\n", handle
);
1117 io
->u
.Status
= STATUS_INVALID_PARAMETER
;
1120 wine_server_release_fd( handle
, fd
);
1121 return io
->u
.Status
;
1125 /******************************************************************
1126 * NtFlushBuffersFile (NTDLL.@)
1128 * Flush any buffered data on an open file handle.
1131 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
1132 * IoStatusBlock [O] Receives information about the operation on return
1135 * Success: 0. IoStatusBlock is updated.
1136 * Failure: An NTSTATUS error code describing the error.
1138 NTSTATUS WINAPI
NtFlushBuffersFile( HANDLE hFile
, IO_STATUS_BLOCK
* IoStatusBlock
)
1141 HANDLE hEvent
= NULL
;
1143 SERVER_START_REQ( flush_file
)
1145 req
->handle
= hFile
;
1146 ret
= wine_server_call( req
);
1147 hEvent
= reply
->event
;
1152 ret
= NtWaitForSingleObject( hEvent
, FALSE
, NULL
);
1158 /******************************************************************
1159 * NtLockFile (NTDLL.@)
1163 NTSTATUS WINAPI
NtLockFile( HANDLE hFile
, HANDLE lock_granted_event
,
1164 PIO_APC_ROUTINE apc
, void* apc_user
,
1165 PIO_STATUS_BLOCK io_status
, PLARGE_INTEGER offset
,
1166 PLARGE_INTEGER count
, ULONG
* key
, BOOLEAN dont_wait
,
1173 if (apc
|| io_status
|| key
)
1175 FIXME("Unimplemented yet parameter\n");
1176 return STATUS_NOT_IMPLEMENTED
;
1181 SERVER_START_REQ( lock_file
)
1183 req
->handle
= hFile
;
1184 req
->offset_low
= offset
->u
.LowPart
;
1185 req
->offset_high
= offset
->u
.HighPart
;
1186 req
->count_low
= count
->u
.LowPart
;
1187 req
->count_high
= count
->u
.HighPart
;
1188 req
->shared
= !exclusive
;
1189 req
->wait
= !dont_wait
;
1190 ret
= wine_server_call( req
);
1191 handle
= reply
->handle
;
1192 async
= reply
->overlapped
;
1195 if (ret
!= STATUS_PENDING
)
1197 if (!ret
&& lock_granted_event
) NtSetEvent(lock_granted_event
, NULL
);
1203 FIXME( "Async I/O lock wait not implemented, might deadlock\n" );
1204 if (handle
) NtClose( handle
);
1205 return STATUS_PENDING
;
1209 NtWaitForSingleObject( handle
, FALSE
, NULL
);
1216 /* Unix lock conflict, sleep a bit and retry */
1217 time
.QuadPart
= 100 * (ULONGLONG
)10000;
1218 time
.QuadPart
= -time
.QuadPart
;
1219 NtDelayExecution( FALSE
, &time
);
1225 /******************************************************************
1226 * NtUnlockFile (NTDLL.@)
1230 NTSTATUS WINAPI
NtUnlockFile( HANDLE hFile
, PIO_STATUS_BLOCK io_status
,
1231 PLARGE_INTEGER offset
, PLARGE_INTEGER count
,
1236 TRACE( "%p %lx%08lx %lx%08lx\n",
1237 hFile
, offset
->u
.HighPart
, offset
->u
.LowPart
, count
->u
.HighPart
, count
->u
.LowPart
);
1239 if (io_status
|| key
)
1241 FIXME("Unimplemented yet parameter\n");
1242 return STATUS_NOT_IMPLEMENTED
;
1245 SERVER_START_REQ( unlock_file
)
1247 req
->handle
= hFile
;
1248 req
->offset_low
= offset
->u
.LowPart
;
1249 req
->offset_high
= offset
->u
.HighPart
;
1250 req
->count_low
= count
->u
.LowPart
;
1251 req
->count_high
= count
->u
.HighPart
;
1252 status
= wine_server_call( req
);