Regression fixes for Nt{Read|Write}File:
[wine/wine64.git] / dlls / ntdll / file.c
blob96839aa345e3eee123c4fb45c5952bf56173f5b7
1 /*
2 * Copyright 1999, 2000 Juergen Schmied
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "config.h"
20 #include "wine/port.h"
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdio.h>
25 #include <errno.h>
26 #include <assert.h>
27 #ifdef HAVE_UNISTD_H
28 # include <unistd.h>
29 #endif
30 #ifdef HAVE_SYS_ERRNO_H
31 #include <sys/errno.h>
32 #endif
34 #define NONAMELESSUNION
35 #define NONAMELESSSTRUCT
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
38 #include "wine/server.h"
39 #include "async.h"
40 #include "ntdll_misc.h"
41 #include "file.h" /* FIXME */
42 #include "../files/smb.h"
44 #include "winternl.h"
45 #include "winioctl.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
49 /**************************************************************************
50 * NtOpenFile [NTDLL.@]
51 * ZwOpenFile [NTDLL.@]
53 * Open a file.
55 * PARAMS
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
63 * RETURNS
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,
72 ULONG ShareAccess,
73 ULONG OpenOptions)
75 LPWSTR filename;
76 static const WCHAR szDosDevices[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\',0};
77 DOS_FULL_NAME full_name;
78 NTSTATUS r;
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,
101 &full_name))
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;
109 req->inherit = 0;
110 req->sharing = ShareAccess;
111 req->create = OPEN_EXISTING;
112 req->attrs = 0;
113 req->drive_type = GetDriveTypeW( full_name.short_name );
114 wine_server_add_data( req, full_name.long_name, strlen(full_name.long_name) );
115 SetLastError(0);
116 r = wine_server_call( req );
117 *FileHandle = reply->handle;
119 SERVER_END_REQ;
121 return r;
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.
131 * PARAMS
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
144 * RETURNS
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,
155 ULONG ShareAccess,
156 ULONG CreateDisposition,
157 ULONG CreateOptions,
158 PVOID EaBuffer,
159 ULONG EaLength)
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);
166 return 0;
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;
193 PIO_APC_ROUTINE apc;
194 void* apc_user;
195 char *buffer;
196 unsigned int count;
197 unsigned long offset;
198 enum fd_type fd_type;
199 } async_fileio;
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)
206 return 0;
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 )
233 int ret, flags;
235 *fd = -1;
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))))
241 close(*fd);
242 ret = STATUS_PIPE_DISCONNECTED;
244 return ret;
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)
255 int err = errno;
256 DWORD nt;
258 TRACE( "errno = %d\n", errno );
259 switch (err)
261 case EAGAIN: nt = STATUS_SHARING_VIOLATION; break;
262 case EBADF: nt = STATUS_INVALID_HANDLE; break;
263 case ENOSPC: nt = STATUS_DISK_FULL; break;
264 case EPERM:
265 case EROFS:
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;
269 case EMFILE:
270 case ENFILE: nt = STATUS_NO_MORE_FILES; break;
271 case EINVAL:
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: /* ?? */
277 default:
278 FIXME( "Converting errno %d to STATUS_UNSUCCESSFUL\n", err );
279 nt = STATUS_UNSUCCESSFUL;
281 return nt;
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;
294 int result;
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);
303 else
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;
315 return;
318 /* check to see if the transfer is complete */
319 if (result < 0)
321 io_status->u.Status = FILE_GetNtStatus();
322 return;
324 else if (result == 0)
326 io_status->u.Status = io_status->Information ? STATUS_SUCCESS : STATUS_END_OF_FILE;
327 return;
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;
333 else
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.
347 * PARAMS
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)
358 * RETURNS
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;
369 enum fd_type type;
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)
380 if (hEvent)
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))
392 async_fileio* ovp;
393 NTSTATUS ret;
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;
407 ovp->count = length;
408 ovp->offset = offset->s.LowPart;
409 if (offset->s.HighPart) FIXME("NIY-high part\n");
410 ovp->apc = apc;
411 ovp->apc_user = apc_user;
412 ovp->buffer = buffer;
413 ovp->fd_type = type;
415 io_status->Information = 0;
416 ret = register_new_async(&ovp->async);
417 if (ret != STATUS_SUCCESS)
418 return ret;
419 if (flags & FD_FLAG_TIMEOUT)
421 NtWaitForSingleObject(hEvent, TRUE, NULL);
422 NtClose(hEvent);
424 else
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;
434 switch (type)
436 case FD_TYPE_SMB:
437 FIXME("NIY-SMB\n");
438 close(unix_handle);
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;
444 break;
446 default:
447 FIXME("Unsupported type of fd %d\n", type);
448 if (unix_handle == -1) close(unix_handle);
449 return STATUS_INVALID_HANDLE;
452 if (offset)
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)
461 close(unix_handle);
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();
471 break;
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;
487 int result;
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);
496 else
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;
507 return;
510 /* check to see if the transfer is complete */
511 if (result < 0)
513 io_status->u.Status = FILE_GetNtStatus();
514 return;
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.
528 * PARAMS
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)
539 * RETURNS
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;
551 enum fd_type type;
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))
566 async_fileio* ovp;
567 NTSTATUS ret;
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;
581 ovp->count = length;
582 ovp->offset = offset->s.LowPart;
583 if (offset->s.HighPart) FIXME("NIY-high part\n");
584 ovp->apc = apc;
585 ovp->apc_user = apc_user;
586 ovp->buffer = (void*)buffer;
587 ovp->fd_type = type;
589 io_status->Information = 0;
590 ret = register_new_async(&ovp->async);
591 if (ret != STATUS_SUCCESS)
592 return ret;
593 if (flags & FD_FLAG_TIMEOUT)
595 NtWaitForSingleObject(hEvent, TRUE, NULL);
596 NtClose(hEvent);
598 else
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;
608 switch (type)
610 case FD_TYPE_SMB:
611 FIXME("NIY-SMB\n");
612 close(unix_handle);
613 return STATUS_NOT_IMPLEMENTED;
615 case FD_TYPE_DEFAULT:
616 /* normal unix files */
617 if (unix_handle == -1) return STATUS_INVALID_HANDLE;
618 break;
620 default:
621 FIXME("Unsupported type of fd %d\n", type);
622 if (unix_handle == -1) close(unix_handle);
623 return STATUS_INVALID_HANDLE;
626 if (offset)
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)
635 close(unix_handle);
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();
647 break;
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.
659 * PARAMS
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
671 * RETURNS
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,
679 ULONG IoControlCode,
680 PVOID InputBuffer,
681 ULONG InputBufferSize,
682 PVOID OutputBuffer,
683 ULONG OutputBufferSize)
685 DWORD clientID = 0;
686 char str[3];
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;
699 SERVER_END_REQ;
701 if (!clientID) return STATUS_INVALID_PARAMETER;
702 strcpy(str, "A:");
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);
741 return 0;
744 /******************************************************************************
745 * NtSetVolumeInformationFile [NTDLL.@]
746 * ZwSetVolumeInformationFile [NTDLL.@]
748 * Set volume information for an open file handle.
750 * PARAMS
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
757 * RETURNS
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,
764 PVOID FsInformation,
765 ULONG Length,
766 FS_INFORMATION_CLASS FsInformationClass)
768 FIXME("(%p,%p,%p,0x%08lx,0x%08x) stub\n",
769 FileHandle,IoStatusBlock,FsInformation,Length,FsInformationClass);
770 return 0;
773 /******************************************************************************
774 * NtQueryInformationFile [NTDLL.@]
775 * ZwQueryInformationFile [NTDLL.@]
777 * Get information about an open file handle.
779 * PARAMS
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
786 * RETURNS
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,
791 PVOID ptr, LONG len,
792 FILE_INFORMATION_CLASS class)
794 NTSTATUS status;
795 LONG used = 0;
796 BYTE answer[256];
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);
801 switch (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 )
810 req->handle = hFile;
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;
825 used = sizeof(*fbi);
827 else status = STATUS_INVALID_HANDLE; /* FIXME ??? */
830 SERVER_END_REQ;
831 if (used)
833 RtlSecondsSince1970ToTime(wt, &fbi->CreationTime);
834 RtlSecondsSince1970ToTime(wt, &fbi->LastWriteTime);
835 RtlSecondsSince1970ToTime(ct, &fbi->ChangeTime);
836 RtlSecondsSince1970ToTime(at, &fbi->LastAccessTime);
839 break;
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 )
847 req->handle = hFile;
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);
865 used = sizeof(*fsi);
867 else status = STATUS_INVALID_HANDLE; /* FIXME ??? */
870 SERVER_END_REQ;
872 break;
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 )
880 req->handle = hFile;
881 req->low = 0;
882 req->high = 0;
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;
888 used = sizeof(*fpi);
891 SERVER_END_REQ;
893 break;
894 default:
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;
901 return status;
902 too_small:
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.
913 * PARAMS
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
920 * RETURNS
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);
932 switch (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 )
941 req->handle = hFile;
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 );
947 SERVER_END_REQ;
948 status = STATUS_SUCCESS;
950 break;
951 default:
952 FIXME("Unsupported class (%d)\n", class);
953 return STATUS_NOT_IMPLEMENTED;
955 io_status->u.Status = status;
956 io_status->Information = 0;
957 return status;
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,
971 IN ULONG Length,
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);
981 return 0;
984 /******************************************************************************
985 * NtQueryVolumeInformationFile [NTDLL.@]
986 * ZwQueryVolumeInformationFile [NTDLL.@]
988 * Get volume information for an open file handle.
990 * PARAMS
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
997 * RETURNS
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,
1005 IN ULONG Length,
1006 IN FS_INFORMATION_CLASS FSInformationClass)
1008 ULONG len = 0;
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 );
1017 break;
1018 case FileFsLabelInformation:
1019 len = 0;
1020 break;
1022 case FileFsSizeInformation:
1023 len = sizeof( FILE_FS_SIZE_INFORMATION );
1024 break;
1026 case FileFsDeviceInformation:
1027 len = sizeof( FILE_FS_DEVICE_INFORMATION );
1028 break;
1029 case FileFsAttributeInformation:
1030 len = sizeof( FILE_FS_ATTRIBUTE_INFORMATION );
1031 break;
1033 case FileFsControlInformation:
1034 len = 0;
1035 break;
1037 case FileFsFullSizeInformation:
1038 len = 0;
1039 break;
1041 case FileFsObjectIdInformation:
1042 len = 0;
1043 break;
1045 case FileFsMaximumInformation:
1046 len = 0;
1047 break;
1050 if (Length < len)
1051 return STATUS_BUFFER_TOO_SMALL;
1053 switch ( FSInformationClass )
1055 case FileFsVolumeInformation:
1056 break;
1057 case FileFsLabelInformation:
1058 break;
1060 case FileFsSizeInformation:
1061 break;
1063 case FileFsDeviceInformation:
1064 if (FSInformation)
1066 FILE_FS_DEVICE_INFORMATION * DeviceInfo = FSInformation;
1067 DeviceInfo->DeviceType = FILE_DEVICE_DISK;
1068 DeviceInfo->Characteristics = 0;
1069 break;
1071 case FileFsAttributeInformation:
1072 break;
1074 case FileFsControlInformation:
1075 break;
1077 case FileFsFullSizeInformation:
1078 break;
1080 case FileFsObjectIdInformation:
1081 break;
1083 case FileFsMaximumInformation:
1084 break;
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.
1096 * PARAMS
1097 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
1098 * IoStatusBlock [O] Receives information about the operation on return
1100 * RETURNS
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 )
1106 NTSTATUS ret;
1107 HANDLE hEvent = NULL;
1109 SERVER_START_REQ( flush_file )
1111 req->handle = hFile;
1112 ret = wine_server_call( req );
1113 hEvent = reply->event;
1115 SERVER_END_REQ;
1116 if (!ret && hEvent)
1118 ret = NtWaitForSingleObject( hEvent, FALSE, NULL );
1119 NtClose( hEvent );
1121 return ret;
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,
1133 BOOLEAN exclusive )
1135 NTSTATUS ret;
1136 HANDLE handle;
1137 BOOLEAN async;
1139 if (apc || io_status || key)
1141 FIXME("Unimplemented yet parameter\n");
1142 return STATUS_NOT_IMPLEMENTED;
1145 for (;;)
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;
1160 SERVER_END_REQ;
1161 if (ret != STATUS_PENDING)
1163 if (!ret && lock_granted_event) NtSetEvent(lock_granted_event, NULL);
1164 return ret;
1167 if (async)
1169 FIXME( "Async I/O lock wait not implemented, might deadlock\n" );
1170 if (handle) NtClose( handle );
1171 return STATUS_PENDING;
1173 if (handle)
1175 NtWaitForSingleObject( handle, FALSE, NULL );
1176 NtClose( handle );
1178 else
1180 LARGE_INTEGER time;
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,
1198 PULONG key )
1200 NTSTATUS status;
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 );
1220 SERVER_END_REQ;
1221 return status;