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"
41 #include "file.h" /* FIXME */
42 #include "../files/smb.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(ntdll
);
49 /**************************************************************************
50 * NtOpenFile [NTDLL.@]
51 * ZwOpenFile [NTDLL.@]
56 * FileHandle [O] Variable that receives the file handle on return
57 * DesiredAccess [I] Access desired by the caller to the file
58 * ObjectAttributes [I] Structue describing the file to be opened
59 * IoStatusBlock [O] Receives details about the result of the operation
60 * ShareAccess [I] Type of shared access the caller requires
61 * OpenOptions [I] Options for the file open
64 * Success: 0. FileHandle and IoStatusBlock are updated.
65 * Failure: An NTSTATUS error code describing the error.
67 NTSTATUS WINAPI
NtOpenFile(
68 OUT PHANDLE FileHandle
,
69 ACCESS_MASK DesiredAccess
,
70 POBJECT_ATTRIBUTES ObjectAttributes
,
71 OUT PIO_STATUS_BLOCK IoStatusBlock
,
76 static const WCHAR szDosDevices
[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\',0};
77 DOS_FULL_NAME full_name
;
80 FIXME("(%p,0x%08lx,%p,%p,0x%08lx,0x%08lx) partial stub\n",
81 FileHandle
, DesiredAccess
, ObjectAttributes
,
82 IoStatusBlock
, ShareAccess
, OpenOptions
);
84 dump_ObjectAttributes (ObjectAttributes
);
86 if(ObjectAttributes
->RootDirectory
)
88 FIXME("Object root directory unknown %p\n",
89 ObjectAttributes
->RootDirectory
);
90 return STATUS_OBJECT_NAME_NOT_FOUND
;
93 filename
= ObjectAttributes
->ObjectName
->Buffer
;
95 /* FIXME: DOSFS stuff should call here, not vice-versa */
96 if(strncmpW(filename
, szDosDevices
, strlenW(szDosDevices
)))
97 return STATUS_OBJECT_NAME_NOT_FOUND
;
99 /* FIXME: this calls SetLastError() -> bad */
100 if(!DOSFS_GetFullName(&filename
[strlenW(szDosDevices
)], TRUE
,
102 return STATUS_OBJECT_NAME_NOT_FOUND
;
104 /* FIXME: modify server protocol so
105 create file takes an OBJECT_ATTRIBUTES structure */
106 SERVER_START_REQ( create_file
)
108 req
->access
= DesiredAccess
;
110 req
->sharing
= ShareAccess
;
111 req
->create
= OPEN_EXISTING
;
113 req
->drive_type
= GetDriveTypeW( full_name
.short_name
);
114 wine_server_add_data( req
, full_name
.long_name
, strlen(full_name
.long_name
) );
116 r
= wine_server_call( req
);
117 *FileHandle
= reply
->handle
;
124 /**************************************************************************
125 * NtCreateFile [NTDLL.@]
126 * ZwCreateFile [NTDLL.@]
128 * Either create a new file or directory, or open an existing file, device,
129 * directory or volume.
132 * FileHandle [O] Points to a variable which receives the file handle on return
133 * DesiredAccess [I] Desired access to the file
134 * ObjectAttributes [I] Structure describing the file
135 * IoStatusBlock [O] Receives information about the operation on return
136 * AllocationSize [I] Initial size of the file in bytes
137 * FileAttributes [I] Attributes to create the file with
138 * ShareAccess [I] Type of shared access the caller would like to the file
139 * CreateDisposition [I] Specifies what to do, depending on whether the file already exists
140 * CreateOptions [I] Options for creating a new file
141 * EaBuffer [I] Undocumented
142 * EaLength [I] Undocumented
145 * Success: 0. FileHandle and IoStatusBlock are updated.
146 * Failure: An NTSTATUS error code describing the error.
148 NTSTATUS WINAPI
NtCreateFile(
149 OUT PHANDLE FileHandle
,
150 ACCESS_MASK DesiredAccess
,
151 POBJECT_ATTRIBUTES ObjectAttributes
,
152 OUT PIO_STATUS_BLOCK IoStatusBlock
,
153 PLARGE_INTEGER AllocateSize
,
154 ULONG FileAttributes
,
156 ULONG CreateDisposition
,
161 FIXME("(%p,0x%08lx,%p,%p,%p,0x%08lx,0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx) stub\n",
162 FileHandle
,DesiredAccess
,ObjectAttributes
,
163 IoStatusBlock
,AllocateSize
,FileAttributes
,
164 ShareAccess
,CreateDisposition
,CreateOptions
,EaBuffer
,EaLength
);
165 dump_ObjectAttributes (ObjectAttributes
);
169 /***********************************************************************
170 * Asynchronous file I/O *
172 static DWORD
fileio_get_async_count(const async_private
*ovp
);
173 static void CALLBACK
fileio_call_completion_func(ULONG_PTR data
);
174 static void fileio_async_cleanup(async_private
*ovp
);
176 static async_ops fileio_async_ops
=
178 fileio_get_async_count
, /* get_count */
179 fileio_call_completion_func
, /* call_completion */
180 fileio_async_cleanup
/* cleanup */
183 static async_ops fileio_nocomp_async_ops
=
185 fileio_get_async_count
, /* get_count */
186 NULL
, /* call_completion */
187 fileio_async_cleanup
/* cleanup */
190 typedef struct async_fileio
192 struct async_private async
;
197 unsigned long offset
;
198 enum fd_type fd_type
;
201 static DWORD
fileio_get_async_count(const struct async_private
*ovp
)
203 async_fileio
*fileio
= (async_fileio
*) ovp
;
205 if (fileio
->count
< fileio
->async
.iosb
->Information
)
207 return fileio
->count
- fileio
->async
.iosb
->Information
;
210 static void CALLBACK
fileio_call_completion_func(ULONG_PTR data
)
212 async_fileio
*ovp
= (async_fileio
*) data
;
213 TRACE("data: %p\n", ovp
);
215 ovp
->apc( ovp
->apc_user
, ovp
->async
.iosb
, ovp
->async
.iosb
->Information
);
217 fileio_async_cleanup( &ovp
->async
);
220 static void fileio_async_cleanup( struct async_private
*ovp
)
222 RtlFreeHeap( ntdll_get_process_heap(), 0, ovp
);
225 /***********************************************************************
226 * FILE_GetUnixHandleType
228 * Retrieve the Unix handle corresponding to a file handle.
229 * Returns -1 on failure.
231 static int FILE_GetUnixHandleType( HANDLE handle
, DWORD access
, enum fd_type
*type
, int *flags_ptr
, int *fd
)
236 ret
= wine_server_handle_to_fd( handle
, access
, fd
, type
, &flags
);
237 if (flags_ptr
) *flags_ptr
= flags
;
238 if (!ret
&& (((access
& GENERIC_READ
) && (flags
& FD_FLAG_RECV_SHUTDOWN
)) ||
239 ((access
& GENERIC_WRITE
) && (flags
& FD_FLAG_SEND_SHUTDOWN
))))
242 ret
= STATUS_PIPE_DISCONNECTED
;
247 /***********************************************************************
248 * FILE_GetNtStatus(void)
250 * Retrieve the Nt Status code from errno.
251 * Try to be consistent with FILE_SetDosError().
253 static DWORD
FILE_GetNtStatus(void)
258 TRACE( "errno = %d\n", errno
);
261 case EAGAIN
: nt
= STATUS_SHARING_VIOLATION
; break;
262 case EBADF
: nt
= STATUS_INVALID_HANDLE
; break;
263 case ENOSPC
: nt
= STATUS_DISK_FULL
; break;
266 case EACCES
: nt
= STATUS_ACCESS_DENIED
; break;
267 case ENOENT
: nt
= STATUS_SHARING_VIOLATION
; break;
268 case EISDIR
: nt
= STATUS_FILE_IS_A_DIRECTORY
; break;
270 case ENFILE
: nt
= STATUS_NO_MORE_FILES
; break;
272 case ENOTEMPTY
: nt
= STATUS_DIRECTORY_NOT_EMPTY
; break;
273 case EPIPE
: nt
= STATUS_PIPE_BROKEN
; break;
274 case ENOEXEC
: /* ?? */
275 case ESPIPE
: /* ?? */
276 case EEXIST
: /* ?? */
278 FIXME( "Converting errno %d to STATUS_UNSUCCESSFUL\n", err
);
279 nt
= STATUS_UNSUCCESSFUL
;
284 /***********************************************************************
285 * FILE_AsyncReadService (INTERNAL)
287 * This function is called while the client is waiting on the
288 * server, so we can't make any server calls here.
290 static void FILE_AsyncReadService(async_private
*ovp
)
292 async_fileio
*fileio
= (async_fileio
*) ovp
;
293 IO_STATUS_BLOCK
* io_status
= fileio
->async
.iosb
;
295 int already
= io_status
->Information
;
297 TRACE("%p %p\n", io_status
, fileio
->buffer
);
299 /* check to see if the data is ready (non-blocking) */
301 if ( fileio
->fd_type
== FD_TYPE_SOCKET
)
302 result
= read(ovp
->fd
, &fileio
->buffer
[already
], fileio
->count
- already
);
305 result
= pread(ovp
->fd
, &fileio
->buffer
[already
], fileio
->count
- already
,
306 fileio
->offset
+ already
);
307 if ((result
< 0) && (errno
== ESPIPE
))
308 result
= read(ovp
->fd
, &fileio
->buffer
[already
], fileio
->count
- already
);
311 if ((result
< 0) && ((errno
== EAGAIN
) || (errno
== EINTR
)))
313 TRACE("Deferred read %d\n",errno
);
314 io_status
->u
.Status
= STATUS_PENDING
;
318 /* check to see if the transfer is complete */
321 io_status
->u
.Status
= FILE_GetNtStatus();
324 else if (result
== 0)
326 io_status
->u
.Status
= io_status
->Information
? STATUS_SUCCESS
: STATUS_END_OF_FILE
;
330 io_status
->Information
+= result
;
331 if (io_status
->Information
>= fileio
->count
|| fileio
->fd_type
== FD_TYPE_SOCKET
)
332 io_status
->u
.Status
= STATUS_SUCCESS
;
334 io_status
->u
.Status
= STATUS_PENDING
;
336 TRACE("read %d more bytes %ld/%d so far\n",
337 result
, io_status
->Information
, fileio
->count
);
341 /******************************************************************************
342 * NtReadFile [NTDLL.@]
343 * ZwReadFile [NTDLL.@]
345 * Read from an open file handle.
348 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
349 * Event [I] Event to signal upon completion (or NULL)
350 * ApcRoutine [I] Callback to call upon completion (or NULL)
351 * ApcContext [I] Context for ApcRoutine (or NULL)
352 * IoStatusBlock [O] Receives information about the operation on return
353 * Buffer [O] Destination for the data read
354 * Length [I] Size of Buffer
355 * ByteOffset [O] Destination for the new file pointer position (or NULL)
356 * Key [O] Function unknown (may be NULL)
359 * Success: 0. IoStatusBlock is updated, and the Information member contains
360 * The number of bytes read.
361 * Failure: An NTSTATUS error code describing the error.
363 NTSTATUS WINAPI
NtReadFile(HANDLE hFile
, HANDLE hEvent
,
364 PIO_APC_ROUTINE apc
, void* apc_user
,
365 PIO_STATUS_BLOCK io_status
, void* buffer
, ULONG length
,
366 PLARGE_INTEGER offset
, PULONG key
)
368 int unix_handle
, flags
;
371 TRACE("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%p),partial stub!\n",
372 hFile
,hEvent
,apc
,apc_user
,io_status
,buffer
,length
,offset
,key
);
374 io_status
->Information
= 0;
375 io_status
->u
.Status
= FILE_GetUnixHandleType( hFile
, GENERIC_READ
, &type
, &flags
, &unix_handle
);
376 if (io_status
->u
.Status
) return io_status
->u
.Status
;
378 if (flags
& FD_FLAG_TIMEOUT
)
382 /* this shouldn't happen, but check it */
383 FIXME("NIY-hEvent\n");
384 return STATUS_NOT_IMPLEMENTED
;
386 io_status
->u
.Status
= NtCreateEvent(&hEvent
, SYNCHRONIZE
, NULL
, 0, 0);
387 if (io_status
->u
.Status
) return io_status
->u
.Status
;
390 if (flags
& (FD_FLAG_OVERLAPPED
|FD_FLAG_TIMEOUT
))
395 if (unix_handle
< 0) return STATUS_INVALID_HANDLE
;
397 ovp
= RtlAllocateHeap(ntdll_get_process_heap(), 0, sizeof(async_fileio
));
398 if (!ovp
) return STATUS_NO_MEMORY
;
400 ovp
->async
.ops
= (apc
? &fileio_async_ops
: &fileio_nocomp_async_ops
);
401 ovp
->async
.handle
= hFile
;
402 ovp
->async
.fd
= unix_handle
;
403 ovp
->async
.type
= ASYNC_TYPE_READ
;
404 ovp
->async
.func
= FILE_AsyncReadService
;
405 ovp
->async
.event
= hEvent
;
406 ovp
->async
.iosb
= io_status
;
408 ovp
->offset
= offset
->s
.LowPart
;
409 if (offset
->s
.HighPart
) FIXME("NIY-high part\n");
411 ovp
->apc_user
= apc_user
;
412 ovp
->buffer
= buffer
;
415 io_status
->Information
= 0;
416 ret
= register_new_async(&ovp
->async
);
417 if (ret
!= STATUS_SUCCESS
)
419 if (flags
& FD_FLAG_TIMEOUT
)
421 NtWaitForSingleObject(hEvent
, TRUE
, NULL
);
426 LARGE_INTEGER timeout
;
428 /* let some APC be run, this will read some already pending data */
429 timeout
.s
.LowPart
= timeout
.s
.HighPart
= 0;
430 NtDelayExecution( TRUE
, &timeout
);
432 return io_status
->u
.Status
;
439 return SMB_ReadFile(hFile
, buffer
, length
, io_status
);
441 case FD_TYPE_DEFAULT
:
442 /* normal unix files */
443 if (unix_handle
== -1) return STATUS_INVALID_HANDLE
;
447 FIXME("Unsupported type of fd %d\n", type
);
448 if (unix_handle
== -1) close(unix_handle
);
449 return STATUS_INVALID_HANDLE
;
454 FILE_POSITION_INFORMATION fpi
;
456 fpi
.CurrentByteOffset
= *offset
;
457 io_status
->u
.Status
= NtSetInformationFile(hFile
, io_status
, &fpi
, sizeof(fpi
),
458 FilePositionInformation
);
459 if (io_status
->u
.Status
)
462 return io_status
->u
.Status
;
465 /* code for synchronous reads */
466 while ((io_status
->Information
= read( unix_handle
, buffer
, length
)) == -1)
468 if ((errno
== EAGAIN
) || (errno
== EINTR
)) continue;
469 if (errno
== EFAULT
) FIXME( "EFAULT handling broken for now\n" );
470 io_status
->u
.Status
= FILE_GetNtStatus();
473 close( unix_handle
);
474 return io_status
->u
.Status
;
477 /***********************************************************************
478 * FILE_AsyncWriteService (INTERNAL)
480 * This function is called while the client is waiting on the
481 * server, so we can't make any server calls here.
483 static void FILE_AsyncWriteService(struct async_private
*ovp
)
485 async_fileio
*fileio
= (async_fileio
*) ovp
;
486 PIO_STATUS_BLOCK io_status
= fileio
->async
.iosb
;
488 int already
= io_status
->Information
;
490 TRACE("(%p %p)\n",io_status
,fileio
->buffer
);
492 /* write some data (non-blocking) */
494 if ( fileio
->fd_type
== FD_TYPE_SOCKET
)
495 result
= write(ovp
->fd
, &fileio
->buffer
[already
], fileio
->count
- already
);
498 result
= pwrite(ovp
->fd
, &fileio
->buffer
[already
], fileio
->count
- already
,
499 fileio
->offset
+ already
);
500 if ((result
< 0) && (errno
== ESPIPE
))
501 result
= write(ovp
->fd
, &fileio
->buffer
[already
], fileio
->count
- already
);
504 if ((result
< 0) && ((errno
== EAGAIN
) || (errno
== EINTR
)))
506 io_status
->u
.Status
= STATUS_PENDING
;
510 /* check to see if the transfer is complete */
513 io_status
->u
.Status
= FILE_GetNtStatus();
517 io_status
->Information
+= result
;
518 io_status
->u
.Status
= (io_status
->Information
< fileio
->count
) ? STATUS_PENDING
: STATUS_SUCCESS
;
519 TRACE("wrote %d more bytes %ld/%d so far\n",result
,io_status
->Information
,fileio
->count
);
522 /******************************************************************************
523 * NtWriteFile [NTDLL.@]
524 * ZwWriteFile [NTDLL.@]
526 * Write to an open file handle.
529 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
530 * Event [I] Event to signal upon completion (or NULL)
531 * ApcRoutine [I] Callback to call upon completion (or NULL)
532 * ApcContext [I] Context for ApcRoutine (or NULL)
533 * IoStatusBlock [O] Receives information about the operation on return
534 * Buffer [I] Source for the data to write
535 * Length [I] Size of Buffer
536 * ByteOffset [O] Destination for the new file pointer position (or NULL)
537 * Key [O] Function unknown (may be NULL)
540 * Success: 0. IoStatusBlock is updated, and the Information member contains
541 * The number of bytes written.
542 * Failure: An NTSTATUS error code describing the error.
544 NTSTATUS WINAPI
NtWriteFile(HANDLE hFile
, HANDLE hEvent
,
545 PIO_APC_ROUTINE apc
, void* apc_user
,
546 PIO_STATUS_BLOCK io_status
,
547 const void* buffer
, ULONG length
,
548 PLARGE_INTEGER offset
, PULONG key
)
550 int unix_handle
, flags
;
553 TRACE("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%p)!\n",
554 hFile
,hEvent
,apc
,apc_user
,io_status
,buffer
,length
,offset
,key
);
556 TRACE("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%p),partial stub!\n",
557 hFile
,hEvent
,apc
,apc_user
,io_status
,buffer
,length
,offset
,key
);
559 io_status
->Information
= 0;
561 io_status
->u
.Status
= FILE_GetUnixHandleType( hFile
, GENERIC_WRITE
, &type
, &flags
, &unix_handle
);
562 if (io_status
->u
.Status
) return io_status
->u
.Status
;
564 if (flags
& (FD_FLAG_OVERLAPPED
|FD_FLAG_TIMEOUT
))
569 if (unix_handle
< 0) return STATUS_INVALID_HANDLE
;
571 ovp
= RtlAllocateHeap(ntdll_get_process_heap(), 0, sizeof(async_fileio
));
572 if (!ovp
) return STATUS_NO_MEMORY
;
574 ovp
->async
.ops
= (apc
? &fileio_async_ops
: &fileio_nocomp_async_ops
);
575 ovp
->async
.handle
= hFile
;
576 ovp
->async
.fd
= unix_handle
;
577 ovp
->async
.type
= ASYNC_TYPE_WRITE
;
578 ovp
->async
.func
= FILE_AsyncWriteService
;
579 ovp
->async
.event
= hEvent
;
580 ovp
->async
.iosb
= io_status
;
582 ovp
->offset
= offset
->s
.LowPart
;
583 if (offset
->s
.HighPart
) FIXME("NIY-high part\n");
585 ovp
->apc_user
= apc_user
;
586 ovp
->buffer
= (void*)buffer
;
589 io_status
->Information
= 0;
590 ret
= register_new_async(&ovp
->async
);
591 if (ret
!= STATUS_SUCCESS
)
593 if (flags
& FD_FLAG_TIMEOUT
)
595 NtWaitForSingleObject(hEvent
, TRUE
, NULL
);
600 LARGE_INTEGER timeout
;
602 /* let some APC be run, this will write as much data as possible */
603 timeout
.s
.LowPart
= timeout
.s
.HighPart
= 0;
604 NtDelayExecution( TRUE
, &timeout
);
606 return io_status
->u
.Status
;
613 return STATUS_NOT_IMPLEMENTED
;
615 case FD_TYPE_DEFAULT
:
616 /* normal unix files */
617 if (unix_handle
== -1) return STATUS_INVALID_HANDLE
;
621 FIXME("Unsupported type of fd %d\n", type
);
622 if (unix_handle
== -1) close(unix_handle
);
623 return STATUS_INVALID_HANDLE
;
628 FILE_POSITION_INFORMATION fpi
;
630 fpi
.CurrentByteOffset
= *offset
;
631 io_status
->u
.Status
= NtSetInformationFile(hFile
, io_status
, &fpi
, sizeof(fpi
),
632 FilePositionInformation
);
633 if (io_status
->u
.Status
)
636 return io_status
->u
.Status
;
640 /* synchronous file write */
641 while ((io_status
->Information
= write( unix_handle
, buffer
, length
)) == -1)
643 if ((errno
== EAGAIN
) || (errno
== EINTR
)) continue;
644 if (errno
== EFAULT
) FIXME( "EFAULT handling broken for now\n" );
645 if (errno
== ENOSPC
) io_status
->u
.Status
= STATUS_DISK_FULL
;
646 else io_status
->u
.Status
= FILE_GetNtStatus();
649 close( unix_handle
);
650 return io_status
->u
.Status
;
653 /**************************************************************************
654 * NtDeviceIoControlFile [NTDLL.@]
655 * ZwDeviceIoControlFile [NTDLL.@]
657 * Perform an I/O control operation on an open file handle.
660 * DeviceHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
661 * Event [I] Event to signal upon completion (or NULL)
662 * ApcRoutine [I] Callback to call upon completion (or NULL)
663 * ApcContext [I] Context for ApcRoutine (or NULL)
664 * IoStatusBlock [O] Receives information about the operation on return
665 * IoControlCode [I] Control code for the operation to perform
666 * InputBuffer [I] Source for any input data required (or NULL)
667 * InputBufferSize [I] Size of InputBuffer
668 * OutputBuffer [O] Source for any output data returned (or NULL)
669 * OutputBufferSize [I] Size of OutputBuffer
672 * Success: 0. IoStatusBlock is updated.
673 * Failure: An NTSTATUS error code describing the error.
675 NTSTATUS WINAPI
NtDeviceIoControlFile(HANDLE DeviceHandle
, HANDLE hEvent
,
676 PIO_APC_ROUTINE UserApcRoutine
,
677 PVOID UserApcContext
,
678 PIO_STATUS_BLOCK IoStatusBlock
,
681 ULONG InputBufferSize
,
683 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 /* FIXME: clientID hack should disappear */
694 SERVER_START_REQ( get_device_id
)
696 req
->handle
= DeviceHandle
;
697 if (!wine_server_call( req
)) clientID
= reply
->id
;
701 if (!clientID
) return STATUS_INVALID_PARAMETER
;
703 str
[0] += LOBYTE(clientID
);
705 /* FIXME: should use the NTDLL equivalent */
706 if (GetDriveTypeA(str
) == DRIVE_CDROM
)
708 return CDROM_DeviceIoControl(clientID
, DeviceHandle
, hEvent
,
709 UserApcRoutine
, UserApcContext
,
710 IoStatusBlock
, IoControlCode
,
711 InputBuffer
, InputBufferSize
,
712 OutputBuffer
, OutputBufferSize
);
715 FIXME("Unimplemented dwIoControlCode=%08lx\n", IoControlCode
);
716 IoStatusBlock
->u
.Status
= STATUS_NOT_IMPLEMENTED
;
717 IoStatusBlock
->Information
= 0;
718 if (hEvent
) NtSetEvent(hEvent
, NULL
);
719 return STATUS_NOT_IMPLEMENTED
;
722 /******************************************************************************
723 * NtFsControlFile [NTDLL.@]
724 * ZwFsControlFile [NTDLL.@]
726 NTSTATUS WINAPI
NtFsControlFile(
727 IN HANDLE DeviceHandle
,
728 IN HANDLE Event OPTIONAL
,
729 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
730 IN PVOID ApcContext OPTIONAL
,
731 OUT PIO_STATUS_BLOCK IoStatusBlock
,
732 IN ULONG IoControlCode
,
733 IN PVOID InputBuffer
,
734 IN ULONG InputBufferSize
,
735 OUT PVOID OutputBuffer
,
736 IN ULONG OutputBufferSize
)
738 FIXME("(%p,%p,%p,%p,%p,0x%08lx,%p,0x%08lx,%p,0x%08lx): stub\n",
739 DeviceHandle
,Event
,ApcRoutine
,ApcContext
,IoStatusBlock
,IoControlCode
,
740 InputBuffer
,InputBufferSize
,OutputBuffer
,OutputBufferSize
);
744 /******************************************************************************
745 * NtSetVolumeInformationFile [NTDLL.@]
746 * ZwSetVolumeInformationFile [NTDLL.@]
748 * Set volume information for an open file handle.
751 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
752 * IoStatusBlock [O] Receives information about the operation on return
753 * FsInformation [I] Source for volume information
754 * Length [I] Size of FsInformation
755 * FsInformationClass [I] Type of volume information to set
758 * Success: 0. IoStatusBlock is updated.
759 * Failure: An NTSTATUS error code describing the error.
761 NTSTATUS WINAPI
NtSetVolumeInformationFile(
762 IN HANDLE FileHandle
,
763 PIO_STATUS_BLOCK IoStatusBlock
,
766 FS_INFORMATION_CLASS FsInformationClass
)
768 FIXME("(%p,%p,%p,0x%08lx,0x%08x) stub\n",
769 FileHandle
,IoStatusBlock
,FsInformation
,Length
,FsInformationClass
);
773 /******************************************************************************
774 * NtQueryInformationFile [NTDLL.@]
775 * ZwQueryInformationFile [NTDLL.@]
777 * Get information about an open file handle.
780 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
781 * IoStatusBlock [O] Receives information about the operation on return
782 * FileInformation [O] Destination for file information
783 * Length [I] Size of FileInformation
784 * FileInformationClass [I] Type of file information to get
787 * Success: 0. IoStatusBlock and FileInformation are updated.
788 * Failure: An NTSTATUS error code describing the error.
790 NTSTATUS WINAPI
NtQueryInformationFile(HANDLE hFile
, PIO_STATUS_BLOCK io_status
,
792 FILE_INFORMATION_CLASS
class)
797 time_t ct
= 0, wt
= 0, at
= 0;
799 TRACE("(%p,%p,%p,0x%08lx,0x%08x)\n", hFile
, io_status
, ptr
, len
, class);
803 case FileBasicInformation
:
805 FILE_BASIC_INFORMATION
* fbi
= (FILE_BASIC_INFORMATION
*)answer
;
806 if (sizeof(answer
) < sizeof(*fbi
)) goto too_small
;
808 SERVER_START_REQ( get_file_info
)
811 if (!(status
= wine_server_call( req
)))
813 /* FIXME: which file types are supported ?
814 * Serial ports (FILE_TYPE_CHAR) are not,
815 * and MSDN also says that pipes are not supported.
816 * FILE_TYPE_REMOTE seems to be supported according to
817 * MSDN q234741.txt */
818 if ((reply
->type
== FILE_TYPE_DISK
) ||
819 (reply
->type
== FILE_TYPE_REMOTE
))
821 at
= reply
->access_time
;
822 wt
= reply
->write_time
;
823 ct
= reply
->change_time
;
824 fbi
->FileAttributes
= reply
->attr
;
827 else status
= STATUS_INVALID_HANDLE
; /* FIXME ??? */
833 RtlSecondsSince1970ToTime(wt
, &fbi
->CreationTime
);
834 RtlSecondsSince1970ToTime(wt
, &fbi
->LastWriteTime
);
835 RtlSecondsSince1970ToTime(ct
, &fbi
->ChangeTime
);
836 RtlSecondsSince1970ToTime(at
, &fbi
->LastAccessTime
);
840 case FileStandardInformation
:
842 FILE_STANDARD_INFORMATION
* fsi
= (FILE_STANDARD_INFORMATION
*)answer
;
843 if (sizeof(answer
) < sizeof(*fsi
)) goto too_small
;
845 SERVER_START_REQ( get_file_info
)
848 if (!(status
= wine_server_call( req
)))
850 /* FIXME: which file types are supported ?
851 * Serial ports (FILE_TYPE_CHAR) are not,
852 * and MSDN also says that pipes are not supported.
853 * FILE_TYPE_REMOTE seems to be supported according to
854 * MSDN q234741.txt */
855 if ((reply
->type
== FILE_TYPE_DISK
) ||
856 (reply
->type
== FILE_TYPE_REMOTE
))
858 fsi
->AllocationSize
.s
.HighPart
= reply
->alloc_high
;
859 fsi
->AllocationSize
.s
.LowPart
= reply
->alloc_low
;
860 fsi
->EndOfFile
.s
.HighPart
= reply
->size_high
;
861 fsi
->EndOfFile
.s
.LowPart
= reply
->size_low
;
862 fsi
->NumberOfLinks
= reply
->links
;
863 fsi
->DeletePending
= FALSE
; /* FIXME */
864 fsi
->Directory
= (reply
->attr
& FILE_ATTRIBUTE_DIRECTORY
);
867 else status
= STATUS_INVALID_HANDLE
; /* FIXME ??? */
873 case FilePositionInformation
:
875 FILE_POSITION_INFORMATION
* fpi
= (FILE_POSITION_INFORMATION
*)answer
;
876 if (sizeof(answer
) < sizeof(*fpi
)) goto too_small
;
878 SERVER_START_REQ( set_file_pointer
)
883 req
->whence
= SEEK_CUR
;
884 if (!(status
= wine_server_call( req
)))
886 fpi
->CurrentByteOffset
.s
.HighPart
= reply
->new_high
;
887 fpi
->CurrentByteOffset
.s
.LowPart
= reply
->new_low
;
895 FIXME("Unsupported class (%d)\n", class);
896 return io_status
->u
.Status
= STATUS_NOT_IMPLEMENTED
;
898 if (used
) memcpy(ptr
, answer
, min(used
, len
));
899 io_status
->u
.Status
= status
;
900 io_status
->Information
= len
;
903 io_status
->Information
= 0;
904 return io_status
->u
.Status
= STATUS_BUFFER_TOO_SMALL
;
907 /******************************************************************************
908 * NtSetInformationFile [NTDLL.@]
909 * ZwSetInformationFile [NTDLL.@]
911 * Set information about an open file handle.
914 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
915 * IoStatusBlock [O] Receives information about the operation on return
916 * FileInformation [I] Source for file information
917 * Length [I] Size of FileInformation
918 * FileInformationClass [I] Type of file information to set
921 * Success: 0. IoStatusBlock is updated.
922 * Failure: An NTSTATUS error code describing the error.
924 NTSTATUS WINAPI
NtSetInformationFile(HANDLE hFile
, PIO_STATUS_BLOCK io_status
,
925 PVOID ptr
, ULONG len
,
926 FILE_INFORMATION_CLASS
class)
928 NTSTATUS status
= STATUS_INVALID_PARAMETER_3
;
930 TRACE("(%p,%p,%p,0x%08lx,0x%08x)\n", hFile
, io_status
, ptr
, len
, class);
934 case FilePositionInformation
:
935 if (len
>= sizeof(FILE_POSITION_INFORMATION
))
937 FILE_POSITION_INFORMATION
* fpi
= (FILE_POSITION_INFORMATION
*)ptr
;
939 SERVER_START_REQ( set_file_pointer
)
942 req
->low
= fpi
->CurrentByteOffset
.s
.LowPart
;
943 req
->high
= fpi
->CurrentByteOffset
.s
.HighPart
;
944 req
->whence
= SEEK_SET
;
945 status
= wine_server_call( req
);
948 status
= STATUS_SUCCESS
;
952 FIXME("Unsupported class (%d)\n", class);
953 return STATUS_NOT_IMPLEMENTED
;
955 io_status
->u
.Status
= status
;
956 io_status
->Information
= 0;
960 /******************************************************************************
961 * NtQueryDirectoryFile [NTDLL.@]
962 * ZwQueryDirectoryFile [NTDLL.@]
964 NTSTATUS WINAPI
NtQueryDirectoryFile(
965 IN HANDLE FileHandle
,
966 IN HANDLE Event OPTIONAL
,
967 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
968 IN PVOID ApcContext OPTIONAL
,
969 OUT PIO_STATUS_BLOCK IoStatusBlock
,
970 OUT PVOID FileInformation
,
972 IN FILE_INFORMATION_CLASS FileInformationClass
,
973 IN BOOLEAN ReturnSingleEntry
,
974 IN PUNICODE_STRING FileName OPTIONAL
,
975 IN BOOLEAN RestartScan
)
977 FIXME("(%p %p %p %p %p %p 0x%08lx 0x%08x 0x%08x %p 0x%08x\n",
978 FileHandle
, Event
, ApcRoutine
, ApcContext
, IoStatusBlock
, FileInformation
,
979 Length
, FileInformationClass
, ReturnSingleEntry
,
980 debugstr_us(FileName
),RestartScan
);
984 /******************************************************************************
985 * NtQueryVolumeInformationFile [NTDLL.@]
986 * ZwQueryVolumeInformationFile [NTDLL.@]
988 * Get volume information for an open file handle.
991 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
992 * IoStatusBlock [O] Receives information about the operation on return
993 * FsInformation [O] Destination for volume information
994 * Length [I] Size of FsInformation
995 * FsInformationClass [I] Type of volume information to set
998 * Success: 0. IoStatusBlock and FsInformation are updated.
999 * Failure: An NTSTATUS error code describing the error.
1001 NTSTATUS WINAPI
NtQueryVolumeInformationFile (
1002 IN HANDLE FileHandle
,
1003 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1004 OUT PVOID FSInformation
,
1006 IN FS_INFORMATION_CLASS FSInformationClass
)
1010 FIXME("(%p %p %p 0x%08lx 0x%08x) stub!\n",
1011 FileHandle
, IoStatusBlock
, FSInformation
, Length
, FSInformationClass
);
1013 switch ( FSInformationClass
)
1015 case FileFsVolumeInformation
:
1016 len
= sizeof( FILE_FS_VOLUME_INFORMATION
);
1018 case FileFsLabelInformation
:
1022 case FileFsSizeInformation
:
1023 len
= sizeof( FILE_FS_SIZE_INFORMATION
);
1026 case FileFsDeviceInformation
:
1027 len
= sizeof( FILE_FS_DEVICE_INFORMATION
);
1029 case FileFsAttributeInformation
:
1030 len
= sizeof( FILE_FS_ATTRIBUTE_INFORMATION
);
1033 case FileFsControlInformation
:
1037 case FileFsFullSizeInformation
:
1041 case FileFsObjectIdInformation
:
1045 case FileFsMaximumInformation
:
1051 return STATUS_BUFFER_TOO_SMALL
;
1053 switch ( FSInformationClass
)
1055 case FileFsVolumeInformation
:
1057 case FileFsLabelInformation
:
1060 case FileFsSizeInformation
:
1063 case FileFsDeviceInformation
:
1066 FILE_FS_DEVICE_INFORMATION
* DeviceInfo
= FSInformation
;
1067 DeviceInfo
->DeviceType
= FILE_DEVICE_DISK
;
1068 DeviceInfo
->Characteristics
= 0;
1071 case FileFsAttributeInformation
:
1074 case FileFsControlInformation
:
1077 case FileFsFullSizeInformation
:
1080 case FileFsObjectIdInformation
:
1083 case FileFsMaximumInformation
:
1086 IoStatusBlock
->u
.Status
= STATUS_SUCCESS
;
1087 IoStatusBlock
->Information
= len
;
1088 return STATUS_SUCCESS
;
1091 /******************************************************************
1092 * NtFlushBuffersFile (NTDLL.@)
1094 * Flush any buffered data on an open file handle.
1097 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
1098 * IoStatusBlock [O] Receives information about the operation on return
1101 * Success: 0. IoStatusBlock is updated.
1102 * Failure: An NTSTATUS error code describing the error.
1104 NTSTATUS WINAPI
NtFlushBuffersFile( HANDLE hFile
, IO_STATUS_BLOCK
* IoStatusBlock
)
1107 HANDLE hEvent
= NULL
;
1109 SERVER_START_REQ( flush_file
)
1111 req
->handle
= hFile
;
1112 ret
= wine_server_call( req
);
1113 hEvent
= reply
->event
;
1118 ret
= NtWaitForSingleObject( hEvent
, FALSE
, NULL
);
1124 /******************************************************************
1125 * NtLockFile (NTDLL.@)
1129 NTSTATUS WINAPI
NtLockFile( HANDLE hFile
, HANDLE lock_granted_event
,
1130 PIO_APC_ROUTINE apc
, void* apc_user
,
1131 PIO_STATUS_BLOCK io_status
, PLARGE_INTEGER offset
,
1132 PLARGE_INTEGER count
, ULONG
* key
, BOOLEAN dont_wait
,
1139 if (apc
|| io_status
|| key
)
1141 FIXME("Unimplemented yet parameter\n");
1142 return STATUS_NOT_IMPLEMENTED
;
1147 SERVER_START_REQ( lock_file
)
1149 req
->handle
= hFile
;
1150 req
->offset_low
= offset
->s
.LowPart
;
1151 req
->offset_high
= offset
->s
.HighPart
;
1152 req
->count_low
= count
->s
.LowPart
;
1153 req
->count_high
= count
->s
.HighPart
;
1154 req
->shared
= !exclusive
;
1155 req
->wait
= !dont_wait
;
1156 ret
= wine_server_call( req
);
1157 handle
= reply
->handle
;
1158 async
= reply
->overlapped
;
1161 if (ret
!= STATUS_PENDING
)
1163 if (!ret
&& lock_granted_event
) NtSetEvent(lock_granted_event
, NULL
);
1169 FIXME( "Async I/O lock wait not implemented, might deadlock\n" );
1170 if (handle
) NtClose( handle
);
1171 return STATUS_PENDING
;
1175 NtWaitForSingleObject( handle
, FALSE
, NULL
);
1182 /* Unix lock conflict, sleep a bit and retry */
1183 time
.QuadPart
= 100 * (ULONGLONG
)10000;
1184 time
.QuadPart
= -time
.QuadPart
;
1185 NtDelayExecution( FALSE
, &time
);
1191 /******************************************************************
1192 * NtUnlockFile (NTDLL.@)
1196 NTSTATUS WINAPI
NtUnlockFile( HANDLE hFile
, PIO_STATUS_BLOCK io_status
,
1197 PLARGE_INTEGER offset
, PLARGE_INTEGER count
,
1202 TRACE( "%p %lx%08lx %lx%08lx\n",
1203 hFile
, offset
->s
.HighPart
, offset
->s
.LowPart
, count
->s
.HighPart
, count
->s
.LowPart
);
1205 if (io_status
|| key
)
1207 FIXME("Unimplemented yet parameter\n");
1208 return STATUS_NOT_IMPLEMENTED
;
1211 SERVER_START_REQ( unlock_file
)
1213 req
->handle
= hFile
;
1214 req
->offset_low
= offset
->s
.LowPart
;
1215 req
->offset_high
= offset
->s
.HighPart
;
1216 req
->count_low
= count
->s
.LowPart
;
1217 req
->count_high
= count
->s
.HighPart
;
1218 status
= wine_server_call( req
);