Make DIR_nt_to_unix return STATUS_NO_SUCH_FILE instead of
[wine/multimedia.git] / dlls / ntdll / file.c
blobfdd4e796e49b86e325f9820641f226c5cf148375
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
33 #ifdef HAVE_LINUX_MAJOR_H
34 # include <linux/major.h>
35 #endif
36 #ifdef HAVE_SYS_STATVFS_H
37 # include <sys/statvfs.h>
38 #endif
39 #ifdef HAVE_SYS_PARAM_H
40 # include <sys/param.h>
41 #endif
42 #ifdef HAVE_SYS_TIME_H
43 # include <sys/time.h>
44 #endif
45 #ifdef HAVE_UTIME_H
46 # include <utime.h>
47 #endif
48 #ifdef STATFS_DEFINED_BY_SYS_VFS
49 # include <sys/vfs.h>
50 #else
51 # ifdef STATFS_DEFINED_BY_SYS_MOUNT
52 # include <sys/mount.h>
53 # else
54 # ifdef STATFS_DEFINED_BY_SYS_STATFS
55 # include <sys/statfs.h>
56 # endif
57 # endif
58 #endif
60 #define NONAMELESSUNION
61 #define NONAMELESSSTRUCT
62 #include "wine/unicode.h"
63 #include "wine/debug.h"
64 #include "wine/server.h"
65 #include "async.h"
66 #include "ntdll_misc.h"
68 #include "winternl.h"
69 #include "winioctl.h"
71 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
73 mode_t FILE_umask = 0;
75 #define SECSPERDAY 86400
76 #define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY)
78 /**************************************************************************
79 * NtOpenFile [NTDLL.@]
80 * ZwOpenFile [NTDLL.@]
82 * Open a file.
84 * PARAMS
85 * handle [O] Variable that receives the file handle on return
86 * access [I] Access desired by the caller to the file
87 * attr [I] Structue describing the file to be opened
88 * io [O] Receives details about the result of the operation
89 * sharing [I] Type of shared access the caller requires
90 * options [I] Options for the file open
92 * RETURNS
93 * Success: 0. FileHandle and IoStatusBlock are updated.
94 * Failure: An NTSTATUS error code describing the error.
96 NTSTATUS WINAPI NtOpenFile( PHANDLE handle, ACCESS_MASK access,
97 POBJECT_ATTRIBUTES attr, PIO_STATUS_BLOCK io,
98 ULONG sharing, ULONG options )
100 return NtCreateFile( handle, access, attr, io, NULL, 0,
101 sharing, FILE_OPEN, options, NULL, 0 );
104 /**************************************************************************
105 * NtCreateFile [NTDLL.@]
106 * ZwCreateFile [NTDLL.@]
108 * Either create a new file or directory, or open an existing file, device,
109 * directory or volume.
111 * PARAMS
112 * handle [O] Points to a variable which receives the file handle on return
113 * access [I] Desired access to the file
114 * attr [I] Structure describing the file
115 * io [O] Receives information about the operation on return
116 * alloc_size [I] Initial size of the file in bytes
117 * attributes [I] Attributes to create the file with
118 * sharing [I] Type of shared access the caller would like to the file
119 * disposition [I] Specifies what to do, depending on whether the file already exists
120 * options [I] Options for creating a new file
121 * ea_buffer [I] Undocumented
122 * ea_length [I] Undocumented
124 * RETURNS
125 * Success: 0. handle and io are updated.
126 * Failure: An NTSTATUS error code describing the error.
128 NTSTATUS WINAPI NtCreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATTRIBUTES attr,
129 PIO_STATUS_BLOCK io, PLARGE_INTEGER alloc_size,
130 ULONG attributes, ULONG sharing, ULONG disposition,
131 ULONG options, PVOID ea_buffer, ULONG ea_length )
133 ANSI_STRING unix_name;
134 int check_last, created = FALSE;
136 TRACE("handle=%p access=%08lx name=%s objattr=%08lx root=%p sec=%p io=%p alloc_size=%p\n"
137 "attr=%08lx sharing=%08lx disp=%ld options=%08lx ea=%p.0x%08lx\n",
138 handle, access, debugstr_us(attr->ObjectName), attr->Attributes,
139 attr->RootDirectory, attr->SecurityDescriptor, io, alloc_size,
140 attributes, sharing, disposition, options, ea_buffer, ea_length );
142 if (attr->RootDirectory)
144 FIXME( "RootDirectory %p not supported\n", attr->RootDirectory );
145 return STATUS_OBJECT_NAME_NOT_FOUND;
147 if (alloc_size) FIXME( "alloc_size not supported\n" );
149 check_last = (disposition == FILE_OPEN || disposition == FILE_OVERWRITE);
151 io->u.Status = wine_nt_to_unix_file_name( attr->ObjectName, &unix_name, check_last,
152 !(attr->Attributes & OBJ_CASE_INSENSITIVE) );
154 if (!check_last && io->u.Status == STATUS_NO_SUCH_FILE)
156 created = TRUE;
157 io->u.Status = STATUS_SUCCESS;
160 if (io->u.Status == STATUS_SUCCESS)
162 SERVER_START_REQ( create_file )
164 req->access = access;
165 req->inherit = (attr->Attributes & OBJ_INHERIT) != 0;
166 req->sharing = sharing;
167 req->create = disposition;
168 req->options = options;
169 req->attrs = attributes;
170 wine_server_add_data( req, unix_name.Buffer, unix_name.Length );
171 io->u.Status = wine_server_call( req );
172 *handle = reply->handle;
174 SERVER_END_REQ;
175 RtlFreeAnsiString( &unix_name );
177 else WARN("%s not found (%lx)\n", debugstr_us(attr->ObjectName), io->u.Status );
179 if (io->u.Status == STATUS_SUCCESS)
181 if (created) io->Information = FILE_CREATED;
182 else switch(disposition)
184 case FILE_SUPERSEDE:
185 io->Information = FILE_SUPERSEDED;
186 break;
187 case FILE_CREATE:
188 io->Information = FILE_CREATED;
189 break;
190 case FILE_OPEN:
191 case FILE_OPEN_IF:
192 io->Information = FILE_OPENED;
193 break;
194 case FILE_OVERWRITE:
195 case FILE_OVERWRITE_IF:
196 io->Information = FILE_OVERWRITTEN;
197 break;
201 return io->u.Status;
204 /***********************************************************************
205 * Asynchronous file I/O *
207 static DWORD fileio_get_async_count(const async_private *ovp);
208 static void CALLBACK fileio_call_completion_func(ULONG_PTR data);
209 static void fileio_async_cleanup(async_private *ovp);
211 static async_ops fileio_async_ops =
213 fileio_get_async_count, /* get_count */
214 fileio_call_completion_func, /* call_completion */
215 fileio_async_cleanup /* cleanup */
218 static async_ops fileio_nocomp_async_ops =
220 fileio_get_async_count, /* get_count */
221 NULL, /* call_completion */
222 fileio_async_cleanup /* cleanup */
225 typedef struct async_fileio
227 struct async_private async;
228 PIO_APC_ROUTINE apc;
229 void* apc_user;
230 char *buffer;
231 unsigned int count;
232 unsigned long offset;
233 enum fd_type fd_type;
234 } async_fileio;
236 static DWORD fileio_get_async_count(const struct async_private *ovp)
238 async_fileio *fileio = (async_fileio*) ovp;
240 if (fileio->count < fileio->async.iosb->Information)
241 return 0;
242 return fileio->count - fileio->async.iosb->Information;
245 static void CALLBACK fileio_call_completion_func(ULONG_PTR data)
247 async_fileio *ovp = (async_fileio*) data;
248 TRACE("data: %p\n", ovp);
250 ovp->apc( ovp->apc_user, ovp->async.iosb, ovp->async.iosb->Information );
252 fileio_async_cleanup( &ovp->async );
255 static void fileio_async_cleanup( struct async_private *ovp )
257 RtlFreeHeap( GetProcessHeap(), 0, ovp );
260 /***********************************************************************
261 * FILE_GetNtStatus(void)
263 * Retrieve the Nt Status code from errno.
264 * Try to be consistent with FILE_SetDosError().
266 NTSTATUS FILE_GetNtStatus(void)
268 int err = errno;
270 TRACE( "errno = %d\n", errno );
271 switch (err)
273 case EAGAIN: return STATUS_SHARING_VIOLATION;
274 case EBADF: return STATUS_INVALID_HANDLE;
275 case ENOSPC: return STATUS_DISK_FULL;
276 case EPERM:
277 case EROFS:
278 case EACCES: return STATUS_ACCESS_DENIED;
279 case ENOTDIR: return STATUS_OBJECT_PATH_NOT_FOUND;
280 case ENOENT: return STATUS_OBJECT_NAME_NOT_FOUND;
281 case EISDIR: return STATUS_FILE_IS_A_DIRECTORY;
282 case EMFILE:
283 case ENFILE: return STATUS_TOO_MANY_OPENED_FILES;
284 case EINVAL: return STATUS_INVALID_PARAMETER;
285 case ENOTEMPTY: return STATUS_DIRECTORY_NOT_EMPTY;
286 case EPIPE: return STATUS_PIPE_BROKEN;
287 case EIO: return STATUS_DEVICE_NOT_READY;
288 case ENOEXEC: /* ?? */
289 case ESPIPE: /* ?? */
290 case EEXIST: /* ?? */
291 default:
292 FIXME( "Converting errno %d to STATUS_UNSUCCESSFUL\n", err );
293 return STATUS_UNSUCCESSFUL;
297 /***********************************************************************
298 * FILE_AsyncReadService (INTERNAL)
300 * This function is called while the client is waiting on the
301 * server, so we can't make any server calls here.
303 static void FILE_AsyncReadService(async_private *ovp)
305 async_fileio *fileio = (async_fileio*) ovp;
306 IO_STATUS_BLOCK* io_status = fileio->async.iosb;
307 int result;
308 int already = io_status->Information;
310 TRACE("%p %p\n", io_status, fileio->buffer );
312 /* check to see if the data is ready (non-blocking) */
314 if ( fileio->fd_type == FD_TYPE_SOCKET )
315 result = read(ovp->fd, &fileio->buffer[already], fileio->count - already);
316 else
318 result = pread(ovp->fd, &fileio->buffer[already], fileio->count - already,
319 fileio->offset + already);
320 if ((result < 0) && (errno == ESPIPE))
321 result = read(ovp->fd, &fileio->buffer[already], fileio->count - already);
324 if ((result < 0) && ((errno == EAGAIN) || (errno == EINTR)))
326 TRACE("Deferred read %d\n",errno);
327 io_status->u.Status = STATUS_PENDING;
328 return;
331 /* check to see if the transfer is complete */
332 if (result < 0)
334 io_status->u.Status = FILE_GetNtStatus();
335 return;
337 else if (result == 0)
339 io_status->u.Status = io_status->Information ? STATUS_SUCCESS : STATUS_END_OF_FILE;
340 return;
343 io_status->Information += result;
344 if (io_status->Information >= fileio->count || fileio->fd_type == FD_TYPE_SOCKET )
345 io_status->u.Status = STATUS_SUCCESS;
346 else
347 io_status->u.Status = STATUS_PENDING;
349 TRACE("read %d more bytes %ld/%d so far\n",
350 result, io_status->Information, fileio->count);
354 /******************************************************************************
355 * NtReadFile [NTDLL.@]
356 * ZwReadFile [NTDLL.@]
358 * Read from an open file handle.
360 * PARAMS
361 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
362 * Event [I] Event to signal upon completion (or NULL)
363 * ApcRoutine [I] Callback to call upon completion (or NULL)
364 * ApcContext [I] Context for ApcRoutine (or NULL)
365 * IoStatusBlock [O] Receives information about the operation on return
366 * Buffer [O] Destination for the data read
367 * Length [I] Size of Buffer
368 * ByteOffset [O] Destination for the new file pointer position (or NULL)
369 * Key [O] Function unknown (may be NULL)
371 * RETURNS
372 * Success: 0. IoStatusBlock is updated, and the Information member contains
373 * The number of bytes read.
374 * Failure: An NTSTATUS error code describing the error.
376 NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
377 PIO_APC_ROUTINE apc, void* apc_user,
378 PIO_STATUS_BLOCK io_status, void* buffer, ULONG length,
379 PLARGE_INTEGER offset, PULONG key)
381 int unix_handle, flags;
382 enum fd_type type;
384 TRACE("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%p),partial stub!\n",
385 hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
387 io_status->Information = 0;
388 io_status->u.Status = wine_server_handle_to_fd( hFile, GENERIC_READ, &unix_handle, &type, &flags );
389 if (io_status->u.Status) return io_status->u.Status;
391 if (flags & FD_FLAG_RECV_SHUTDOWN)
393 wine_server_release_fd( hFile, unix_handle );
394 return STATUS_PIPE_DISCONNECTED;
397 if (flags & FD_FLAG_TIMEOUT)
399 if (hEvent)
401 /* this shouldn't happen, but check it */
402 FIXME("NIY-hEvent\n");
403 wine_server_release_fd( hFile, unix_handle );
404 return STATUS_NOT_IMPLEMENTED;
406 io_status->u.Status = NtCreateEvent(&hEvent, SYNCHRONIZE, NULL, 0, 0);
407 if (io_status->u.Status)
409 wine_server_release_fd( hFile, unix_handle );
410 return io_status->u.Status;
414 if (flags & (FD_FLAG_OVERLAPPED|FD_FLAG_TIMEOUT))
416 async_fileio* ovp;
417 NTSTATUS ret;
419 if (!(ovp = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(async_fileio))))
421 wine_server_release_fd( hFile, unix_handle );
422 return STATUS_NO_MEMORY;
424 ovp->async.ops = (apc ? &fileio_async_ops : &fileio_nocomp_async_ops );
425 ovp->async.handle = hFile;
426 ovp->async.fd = unix_handle; /* FIXME */
427 ovp->async.type = ASYNC_TYPE_READ;
428 ovp->async.func = FILE_AsyncReadService;
429 ovp->async.event = hEvent;
430 ovp->async.iosb = io_status;
431 ovp->count = length;
432 if ( offset == NULL )
433 ovp->offset = 0;
434 else
436 ovp->offset = offset->u.LowPart;
437 if (offset->u.HighPart) FIXME("NIY-high part\n");
439 ovp->apc = apc;
440 ovp->apc_user = apc_user;
441 ovp->buffer = buffer;
442 ovp->fd_type = type;
444 io_status->Information = 0;
445 ret = register_new_async(&ovp->async);
446 if (ret != STATUS_SUCCESS)
447 return ret;
448 if (flags & FD_FLAG_TIMEOUT)
450 NtWaitForSingleObject(hEvent, TRUE, NULL);
451 NtClose(hEvent);
453 else
455 LARGE_INTEGER timeout;
457 /* let some APC be run, this will read some already pending data */
458 timeout.u.LowPart = timeout.u.HighPart = 0;
459 NtDelayExecution( TRUE, &timeout );
461 return io_status->u.Status;
463 switch (type)
465 case FD_TYPE_SMB:
466 FIXME("NIY-SMB\n");
467 /* FIXME */
468 /* return SMB_ReadFile(hFile, unix_handle, buffer, length, io_status); */
469 wine_server_release_fd( hFile, unix_handle );
470 return STATUS_INVALID_HANDLE;
472 case FD_TYPE_DEFAULT:
473 /* normal unix file */
474 break;
476 default:
477 FIXME("Unsupported type of fd %d\n", type);
478 wine_server_release_fd( hFile, unix_handle );
479 return STATUS_INVALID_HANDLE;
482 if (offset)
484 FILE_POSITION_INFORMATION fpi;
486 fpi.CurrentByteOffset = *offset;
487 io_status->u.Status = NtSetInformationFile(hFile, io_status, &fpi, sizeof(fpi),
488 FilePositionInformation);
489 if (io_status->u.Status)
491 wine_server_release_fd( hFile, unix_handle );
492 return io_status->u.Status;
495 /* code for synchronous reads */
496 while ((io_status->Information = read( unix_handle, buffer, length )) == -1)
498 if ((errno == EAGAIN) || (errno == EINTR)) continue;
499 if (errno == EFAULT) FIXME( "EFAULT handling broken for now\n" );
500 io_status->u.Status = FILE_GetNtStatus();
501 break;
503 wine_server_release_fd( hFile, unix_handle );
504 return io_status->u.Status;
507 /***********************************************************************
508 * FILE_AsyncWriteService (INTERNAL)
510 * This function is called while the client is waiting on the
511 * server, so we can't make any server calls here.
513 static void FILE_AsyncWriteService(struct async_private *ovp)
515 async_fileio *fileio = (async_fileio *) ovp;
516 PIO_STATUS_BLOCK io_status = fileio->async.iosb;
517 int result;
518 int already = io_status->Information;
520 TRACE("(%p %p)\n",io_status,fileio->buffer);
522 /* write some data (non-blocking) */
524 if ( fileio->fd_type == FD_TYPE_SOCKET )
525 result = write(ovp->fd, &fileio->buffer[already], fileio->count - already);
526 else
528 result = pwrite(ovp->fd, &fileio->buffer[already], fileio->count - already,
529 fileio->offset + already);
530 if ((result < 0) && (errno == ESPIPE))
531 result = write(ovp->fd, &fileio->buffer[already], fileio->count - already);
534 if ((result < 0) && ((errno == EAGAIN) || (errno == EINTR)))
536 io_status->u.Status = STATUS_PENDING;
537 return;
540 /* check to see if the transfer is complete */
541 if (result < 0)
543 io_status->u.Status = FILE_GetNtStatus();
544 return;
547 io_status->Information += result;
548 io_status->u.Status = (io_status->Information < fileio->count) ? STATUS_PENDING : STATUS_SUCCESS;
549 TRACE("wrote %d more bytes %ld/%d so far\n",result,io_status->Information,fileio->count);
552 /******************************************************************************
553 * NtWriteFile [NTDLL.@]
554 * ZwWriteFile [NTDLL.@]
556 * Write to an open file handle.
558 * PARAMS
559 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
560 * Event [I] Event to signal upon completion (or NULL)
561 * ApcRoutine [I] Callback to call upon completion (or NULL)
562 * ApcContext [I] Context for ApcRoutine (or NULL)
563 * IoStatusBlock [O] Receives information about the operation on return
564 * Buffer [I] Source for the data to write
565 * Length [I] Size of Buffer
566 * ByteOffset [O] Destination for the new file pointer position (or NULL)
567 * Key [O] Function unknown (may be NULL)
569 * RETURNS
570 * Success: 0. IoStatusBlock is updated, and the Information member contains
571 * The number of bytes written.
572 * Failure: An NTSTATUS error code describing the error.
574 NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
575 PIO_APC_ROUTINE apc, void* apc_user,
576 PIO_STATUS_BLOCK io_status,
577 const void* buffer, ULONG length,
578 PLARGE_INTEGER offset, PULONG key)
580 int unix_handle, flags;
581 enum fd_type type;
583 TRACE("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%p)!\n",
584 hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
586 TRACE("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%p),partial stub!\n",
587 hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
589 io_status->Information = 0;
590 io_status->u.Status = wine_server_handle_to_fd( hFile, GENERIC_WRITE, &unix_handle, &type, &flags );
591 if (io_status->u.Status) return io_status->u.Status;
593 if (flags & FD_FLAG_SEND_SHUTDOWN)
595 wine_server_release_fd( hFile, unix_handle );
596 return STATUS_PIPE_DISCONNECTED;
599 if (flags & (FD_FLAG_OVERLAPPED|FD_FLAG_TIMEOUT))
601 async_fileio* ovp;
602 NTSTATUS ret;
604 if (!(ovp = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(async_fileio))))
606 wine_server_release_fd( hFile, unix_handle );
607 return STATUS_NO_MEMORY;
609 ovp->async.ops = (apc ? &fileio_async_ops : &fileio_nocomp_async_ops );
610 ovp->async.handle = hFile;
611 ovp->async.fd = unix_handle; /* FIXME */
612 ovp->async.type = ASYNC_TYPE_WRITE;
613 ovp->async.func = FILE_AsyncWriteService;
614 ovp->async.event = hEvent;
615 ovp->async.iosb = io_status;
616 ovp->count = length;
617 if (offset) {
618 ovp->offset = offset->u.LowPart;
619 if (offset->u.HighPart) FIXME("NIY-high part\n");
620 } else {
621 ovp->offset = 0;
623 ovp->apc = apc;
624 ovp->apc_user = apc_user;
625 ovp->buffer = (void*)buffer;
626 ovp->fd_type = type;
628 io_status->Information = 0;
629 ret = register_new_async(&ovp->async);
630 if (ret != STATUS_SUCCESS)
631 return ret;
632 if (flags & FD_FLAG_TIMEOUT)
634 NtWaitForSingleObject(hEvent, TRUE, NULL);
635 NtClose(hEvent);
637 else
639 LARGE_INTEGER timeout;
641 /* let some APC be run, this will write as much data as possible */
642 timeout.u.LowPart = timeout.u.HighPart = 0;
643 NtDelayExecution( TRUE, &timeout );
645 return io_status->u.Status;
647 switch (type)
649 case FD_TYPE_SMB:
650 FIXME("NIY-SMB\n");
651 wine_server_release_fd( hFile, unix_handle );
652 return STATUS_NOT_IMPLEMENTED;
654 case FD_TYPE_DEFAULT:
655 /* normal unix files */
656 if (unix_handle == -1) return STATUS_INVALID_HANDLE;
657 break;
659 default:
660 FIXME("Unsupported type of fd %d\n", type);
661 wine_server_release_fd( hFile, unix_handle );
662 return STATUS_INVALID_HANDLE;
665 if (offset)
667 FILE_POSITION_INFORMATION fpi;
669 fpi.CurrentByteOffset = *offset;
670 io_status->u.Status = NtSetInformationFile(hFile, io_status, &fpi, sizeof(fpi),
671 FilePositionInformation);
672 if (io_status->u.Status)
674 wine_server_release_fd( hFile, unix_handle );
675 return io_status->u.Status;
679 /* synchronous file write */
680 while ((io_status->Information = write( unix_handle, buffer, length )) == -1)
682 if ((errno == EAGAIN) || (errno == EINTR)) continue;
683 if (errno == EFAULT) FIXME( "EFAULT handling broken for now\n" );
684 if (errno == ENOSPC) io_status->u.Status = STATUS_DISK_FULL;
685 else io_status->u.Status = FILE_GetNtStatus();
686 break;
688 wine_server_release_fd( hFile, unix_handle );
689 return io_status->u.Status;
692 /**************************************************************************
693 * NtDeviceIoControlFile [NTDLL.@]
694 * ZwDeviceIoControlFile [NTDLL.@]
696 * Perform an I/O control operation on an open file handle.
698 * PARAMS
699 * DeviceHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
700 * Event [I] Event to signal upon completion (or NULL)
701 * ApcRoutine [I] Callback to call upon completion (or NULL)
702 * ApcContext [I] Context for ApcRoutine (or NULL)
703 * IoStatusBlock [O] Receives information about the operation on return
704 * IoControlCode [I] Control code for the operation to perform
705 * InputBuffer [I] Source for any input data required (or NULL)
706 * InputBufferSize [I] Size of InputBuffer
707 * OutputBuffer [O] Source for any output data returned (or NULL)
708 * OutputBufferSize [I] Size of OutputBuffer
710 * RETURNS
711 * Success: 0. IoStatusBlock is updated.
712 * Failure: An NTSTATUS error code describing the error.
714 NTSTATUS WINAPI NtDeviceIoControlFile(HANDLE DeviceHandle, HANDLE hEvent,
715 PIO_APC_ROUTINE UserApcRoutine,
716 PVOID UserApcContext,
717 PIO_STATUS_BLOCK IoStatusBlock,
718 ULONG IoControlCode,
719 PVOID InputBuffer,
720 ULONG InputBufferSize,
721 PVOID OutputBuffer,
722 ULONG OutputBufferSize)
724 TRACE("(%p,%p,%p,%p,%p,0x%08lx,%p,0x%08lx,%p,0x%08lx)\n",
725 DeviceHandle, hEvent, UserApcRoutine, UserApcContext,
726 IoStatusBlock, IoControlCode,
727 InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize);
729 if (CDROM_DeviceIoControl(DeviceHandle, hEvent,
730 UserApcRoutine, UserApcContext,
731 IoStatusBlock, IoControlCode,
732 InputBuffer, InputBufferSize,
733 OutputBuffer, OutputBufferSize) == STATUS_NO_SUCH_DEVICE)
735 /* it wasn't a CDROM */
736 FIXME("Unimplemented dwIoControlCode=%08lx\n", IoControlCode);
737 IoStatusBlock->u.Status = STATUS_NOT_IMPLEMENTED;
738 IoStatusBlock->Information = 0;
739 if (hEvent) NtSetEvent(hEvent, NULL);
741 return IoStatusBlock->u.Status;
744 /******************************************************************************
745 * NtFsControlFile [NTDLL.@]
746 * ZwFsControlFile [NTDLL.@]
748 NTSTATUS WINAPI NtFsControlFile(
749 IN HANDLE DeviceHandle,
750 IN HANDLE Event OPTIONAL,
751 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
752 IN PVOID ApcContext OPTIONAL,
753 OUT PIO_STATUS_BLOCK IoStatusBlock,
754 IN ULONG IoControlCode,
755 IN PVOID InputBuffer,
756 IN ULONG InputBufferSize,
757 OUT PVOID OutputBuffer,
758 IN ULONG OutputBufferSize)
760 FIXME("(%p,%p,%p,%p,%p,0x%08lx,%p,0x%08lx,%p,0x%08lx): stub\n",
761 DeviceHandle,Event,ApcRoutine,ApcContext,IoStatusBlock,IoControlCode,
762 InputBuffer,InputBufferSize,OutputBuffer,OutputBufferSize);
763 return 0;
766 /******************************************************************************
767 * NtSetVolumeInformationFile [NTDLL.@]
768 * ZwSetVolumeInformationFile [NTDLL.@]
770 * Set volume information for an open file handle.
772 * PARAMS
773 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
774 * IoStatusBlock [O] Receives information about the operation on return
775 * FsInformation [I] Source for volume information
776 * Length [I] Size of FsInformation
777 * FsInformationClass [I] Type of volume information to set
779 * RETURNS
780 * Success: 0. IoStatusBlock is updated.
781 * Failure: An NTSTATUS error code describing the error.
783 NTSTATUS WINAPI NtSetVolumeInformationFile(
784 IN HANDLE FileHandle,
785 PIO_STATUS_BLOCK IoStatusBlock,
786 PVOID FsInformation,
787 ULONG Length,
788 FS_INFORMATION_CLASS FsInformationClass)
790 FIXME("(%p,%p,%p,0x%08lx,0x%08x) stub\n",
791 FileHandle,IoStatusBlock,FsInformation,Length,FsInformationClass);
792 return 0;
795 /******************************************************************************
796 * NtQueryInformationFile [NTDLL.@]
797 * ZwQueryInformationFile [NTDLL.@]
799 * Get information about an open file handle.
801 * PARAMS
802 * hFile [I] Handle returned from ZwOpenFile() or ZwCreateFile()
803 * io [O] Receives information about the operation on return
804 * ptr [O] Destination for file information
805 * len [I] Size of FileInformation
806 * class [I] Type of file information to get
808 * RETURNS
809 * Success: 0. IoStatusBlock and FileInformation are updated.
810 * Failure: An NTSTATUS error code describing the error.
812 NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
813 PVOID ptr, LONG len, FILE_INFORMATION_CLASS class )
815 int fd;
817 TRACE("(%p,%p,%p,0x%08lx,0x%08x)\n", hFile, io, ptr, len, class);
819 io->Information = 0;
820 if ((io->u.Status = wine_server_handle_to_fd( hFile, 0, &fd, NULL, NULL )))
821 return io->u.Status;
823 switch (class)
825 case FileBasicInformation:
827 FILE_BASIC_INFORMATION *info = ptr;
829 if (len < sizeof(*info)) io->u.Status = STATUS_INFO_LENGTH_MISMATCH;
830 else
832 struct stat st;
834 if (fstat( fd, &st ) == -1)
835 io->u.Status = FILE_GetNtStatus();
836 else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
837 io->u.Status = STATUS_INVALID_INFO_CLASS;
838 else
840 if (S_ISDIR(st.st_mode)) info->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
841 else info->FileAttributes = FILE_ATTRIBUTE_ARCHIVE;
842 if (!(st.st_mode & S_IWUSR)) info->FileAttributes |= FILE_ATTRIBUTE_READONLY;
843 RtlSecondsSince1970ToTime( st.st_mtime, &info->CreationTime);
844 RtlSecondsSince1970ToTime( st.st_mtime, &info->LastWriteTime);
845 RtlSecondsSince1970ToTime( st.st_ctime, &info->ChangeTime);
846 RtlSecondsSince1970ToTime( st.st_atime, &info->LastAccessTime);
850 break;
851 case FileStandardInformation:
853 FILE_STANDARD_INFORMATION *info = ptr;
855 if (len < sizeof(*info)) io->u.Status = STATUS_INFO_LENGTH_MISMATCH;
856 else
858 struct stat st;
860 if (fstat( fd, &st ) == -1) io->u.Status = FILE_GetNtStatus();
861 else
863 if ((info->Directory = S_ISDIR(st.st_mode)))
865 info->AllocationSize.QuadPart = 0;
866 info->EndOfFile.QuadPart = 0;
867 info->NumberOfLinks = 1;
868 info->DeletePending = FALSE;
870 else
872 info->AllocationSize.QuadPart = (ULONGLONG)st.st_blocks * 512;
873 info->EndOfFile.QuadPart = st.st_size;
874 info->NumberOfLinks = st.st_nlink;
875 info->DeletePending = FALSE; /* FIXME */
877 io->Information = sizeof(*info);
881 break;
882 case FilePositionInformation:
884 FILE_POSITION_INFORMATION *info = ptr;
886 if (len < sizeof(*info)) io->u.Status = STATUS_INFO_LENGTH_MISMATCH;
887 else
889 off_t res = lseek( fd, 0, SEEK_CUR );
890 if (res == (off_t)-1) io->u.Status = FILE_GetNtStatus();
891 else
893 info->CurrentByteOffset.QuadPart = res;
894 io->Information = sizeof(*info);
898 break;
899 default:
900 FIXME("Unsupported class (%d)\n", class);
901 io->u.Status = STATUS_NOT_IMPLEMENTED;
902 break;
904 wine_server_release_fd( hFile, fd );
905 return io->u.Status;
908 /******************************************************************************
909 * NtSetInformationFile [NTDLL.@]
910 * ZwSetInformationFile [NTDLL.@]
912 * Set information about an open file handle.
914 * PARAMS
915 * handle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
916 * io [O] Receives information about the operation on return
917 * ptr [I] Source for file information
918 * len [I] Size of FileInformation
919 * class [I] Type of file information to set
921 * RETURNS
922 * Success: 0. io is updated.
923 * Failure: An NTSTATUS error code describing the error.
925 NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io,
926 PVOID ptr, ULONG len, FILE_INFORMATION_CLASS class)
928 int fd;
930 TRACE("(%p,%p,%p,0x%08lx,0x%08x)\n", handle, io, ptr, len, class);
932 if ((io->u.Status = wine_server_handle_to_fd( handle, 0, &fd, NULL, NULL )))
933 return io->u.Status;
935 io->u.Status = STATUS_SUCCESS;
936 switch (class)
938 case FileBasicInformation:
939 if (len >= sizeof(FILE_BASIC_INFORMATION))
941 struct stat st;
942 const FILE_BASIC_INFORMATION *info = ptr;
944 #ifdef HAVE_FUTIMES
945 if (info->LastAccessTime.QuadPart || info->LastWriteTime.QuadPart)
947 ULONGLONG sec, nsec;
948 struct timeval tv[2];
950 if (!info->LastAccessTime.QuadPart || !info->LastWriteTime.QuadPart)
953 tv[0].tv_sec = tv[0].tv_usec = 0;
954 tv[1].tv_sec = tv[1].tv_usec = 0;
955 if (!fstat( fd, &st ))
957 tv[0].tv_sec = st.st_atime;
958 tv[1].tv_sec = st.st_mtime;
961 if (info->LastAccessTime.QuadPart)
963 sec = RtlLargeIntegerDivide( info->LastAccessTime.QuadPart, 10000000, &nsec );
964 tv[0].tv_sec = sec - SECS_1601_TO_1970;
965 tv[0].tv_usec = (UINT)nsec / 10;
967 if (info->LastWriteTime.QuadPart)
969 sec = RtlLargeIntegerDivide( info->LastWriteTime.QuadPart, 10000000, &nsec );
970 tv[1].tv_sec = sec - SECS_1601_TO_1970;
971 tv[1].tv_usec = (UINT)nsec / 10;
973 if (futimes( fd, tv ) == -1) io->u.Status = FILE_GetNtStatus();
975 #endif /* HAVE_FUTIMES */
976 if (io->u.Status == STATUS_SUCCESS && info->FileAttributes)
978 if (fstat( fd, &st ) == -1) io->u.Status = FILE_GetNtStatus();
979 else
981 if (info->FileAttributes & FILE_ATTRIBUTE_READONLY)
983 st.st_mode &= ~0222; /* clear write permission bits */
985 else
987 /* add write permission only where we already have read permission */
988 st.st_mode |= (0600 | ((st.st_mode & 044) >> 1)) & (~FILE_umask);
990 if (fchmod( fd, st.st_mode ) == -1) io->u.Status = FILE_GetNtStatus();
994 else io->u.Status = STATUS_INVALID_PARAMETER_3;
995 break;
997 case FilePositionInformation:
998 if (len >= sizeof(FILE_POSITION_INFORMATION))
1000 const FILE_POSITION_INFORMATION *info = ptr;
1002 if (lseek( fd, info->CurrentByteOffset.QuadPart, SEEK_SET ) == (off_t)-1)
1003 io->u.Status = FILE_GetNtStatus();
1005 else io->u.Status = STATUS_INVALID_PARAMETER_3;
1006 break;
1008 default:
1009 FIXME("Unsupported class (%d)\n", class);
1010 io->u.Status = STATUS_NOT_IMPLEMENTED;
1011 break;
1013 wine_server_release_fd( handle, fd );
1014 io->Information = 0;
1015 return io->u.Status;
1019 /******************************************************************************
1020 * NtQueryFullAttributesFile (NTDLL.@)
1022 NTSTATUS WINAPI NtQueryFullAttributesFile( const OBJECT_ATTRIBUTES *attr,
1023 FILE_NETWORK_OPEN_INFORMATION *info )
1025 ANSI_STRING unix_name;
1026 NTSTATUS status;
1028 if (!(status = wine_nt_to_unix_file_name( attr->ObjectName, &unix_name,
1029 TRUE, !(attr->Attributes & OBJ_CASE_INSENSITIVE) )))
1031 struct stat st;
1033 if (stat( unix_name.Buffer, &st ) == -1)
1034 status = FILE_GetNtStatus();
1035 else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
1036 status = STATUS_INVALID_INFO_CLASS;
1037 else
1039 if (S_ISDIR(st.st_mode))
1041 info->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
1042 info->AllocationSize.QuadPart = 0;
1043 info->EndOfFile.QuadPart = 0;
1045 else
1047 info->FileAttributes = FILE_ATTRIBUTE_ARCHIVE;
1048 info->AllocationSize.QuadPart = (ULONGLONG)st.st_blocks * 512;
1049 info->EndOfFile.QuadPart = st.st_size;
1051 if (!(st.st_mode & S_IWUSR)) info->FileAttributes |= FILE_ATTRIBUTE_READONLY;
1052 RtlSecondsSince1970ToTime( st.st_mtime, &info->CreationTime );
1053 RtlSecondsSince1970ToTime( st.st_mtime, &info->LastWriteTime );
1054 RtlSecondsSince1970ToTime( st.st_ctime, &info->ChangeTime );
1055 RtlSecondsSince1970ToTime( st.st_atime, &info->LastAccessTime );
1056 if (DIR_is_hidden_file( attr->ObjectName ))
1057 info->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
1059 RtlFreeAnsiString( &unix_name );
1061 else WARN("%s not found (%lx)\n", debugstr_us(attr->ObjectName), status );
1062 return status;
1066 /******************************************************************************
1067 * NtQueryAttributesFile (NTDLL.@)
1068 * ZwQueryAttributesFile (NTDLL.@)
1070 NTSTATUS WINAPI NtQueryAttributesFile( const OBJECT_ATTRIBUTES *attr, FILE_BASIC_INFORMATION *info )
1072 FILE_NETWORK_OPEN_INFORMATION full_info;
1073 NTSTATUS status;
1075 if (!(status = NtQueryFullAttributesFile( attr, &full_info )))
1077 info->CreationTime.QuadPart = full_info.CreationTime.QuadPart;
1078 info->LastAccessTime.QuadPart = full_info.LastAccessTime.QuadPart;
1079 info->LastWriteTime.QuadPart = full_info.LastWriteTime.QuadPart;
1080 info->ChangeTime.QuadPart = full_info.ChangeTime.QuadPart;
1081 info->FileAttributes = full_info.FileAttributes;
1083 return status;
1087 /******************************************************************************
1088 * NtQueryVolumeInformationFile [NTDLL.@]
1089 * ZwQueryVolumeInformationFile [NTDLL.@]
1091 * Get volume information for an open file handle.
1093 * PARAMS
1094 * handle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
1095 * io [O] Receives information about the operation on return
1096 * buffer [O] Destination for volume information
1097 * length [I] Size of FsInformation
1098 * info_class [I] Type of volume information to set
1100 * RETURNS
1101 * Success: 0. io and buffer are updated.
1102 * Failure: An NTSTATUS error code describing the error.
1104 NTSTATUS WINAPI NtQueryVolumeInformationFile( HANDLE handle, PIO_STATUS_BLOCK io,
1105 PVOID buffer, ULONG length,
1106 FS_INFORMATION_CLASS info_class )
1108 int fd;
1109 struct stat st;
1111 if ((io->u.Status = wine_server_handle_to_fd( handle, 0, &fd, NULL, NULL )) != STATUS_SUCCESS)
1112 return io->u.Status;
1114 io->u.Status = STATUS_NOT_IMPLEMENTED;
1115 io->Information = 0;
1117 switch( info_class )
1119 case FileFsVolumeInformation:
1120 FIXME( "%p: volume info not supported\n", handle );
1121 break;
1122 case FileFsLabelInformation:
1123 FIXME( "%p: label info not supported\n", handle );
1124 break;
1125 case FileFsSizeInformation:
1126 if (length < sizeof(FILE_FS_SIZE_INFORMATION))
1127 io->u.Status = STATUS_BUFFER_TOO_SMALL;
1128 else
1130 FILE_FS_SIZE_INFORMATION *info = buffer;
1131 struct statvfs stvfs;
1133 if (fstat( fd, &st ) < 0)
1135 io->u.Status = FILE_GetNtStatus();
1136 break;
1138 if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
1140 io->u.Status = STATUS_INVALID_DEVICE_REQUEST;
1141 break;
1143 if (fstatvfs( fd, &stvfs ) < 0) io->u.Status = FILE_GetNtStatus();
1144 else
1146 info->TotalAllocationUnits.QuadPart = stvfs.f_blocks;
1147 info->AvailableAllocationUnits.QuadPart = stvfs.f_bavail;
1148 info->SectorsPerAllocationUnit = 1;
1149 info->BytesPerSector = stvfs.f_frsize;
1150 io->Information = sizeof(*info);
1151 io->u.Status = STATUS_SUCCESS;
1154 break;
1155 case FileFsDeviceInformation:
1156 if (length < sizeof(FILE_FS_DEVICE_INFORMATION))
1157 io->u.Status = STATUS_BUFFER_TOO_SMALL;
1158 else
1160 FILE_FS_DEVICE_INFORMATION *info = buffer;
1162 #if defined(linux) && defined(HAVE_FSTATFS)
1163 struct statfs stfs;
1165 info->Characteristics = 0;
1167 if (fstat( fd, &st ) < 0)
1169 io->u.Status = FILE_GetNtStatus();
1170 break;
1172 if (S_ISCHR( st.st_mode ))
1174 switch(major(st.st_rdev))
1176 case MEM_MAJOR:
1177 info->DeviceType = FILE_DEVICE_NULL;
1178 break;
1179 case TTY_MAJOR:
1180 info->DeviceType = FILE_DEVICE_SERIAL_PORT;
1181 break;
1182 case LP_MAJOR:
1183 info->DeviceType = FILE_DEVICE_PARALLEL_PORT;
1184 break;
1185 default:
1186 info->DeviceType = FILE_DEVICE_UNKNOWN;
1187 break;
1190 else if (S_ISBLK( st.st_mode ))
1192 info->DeviceType = FILE_DEVICE_DISK;
1194 else if (S_ISFIFO( st.st_mode ) || S_ISSOCK( st.st_mode ))
1196 info->DeviceType = FILE_DEVICE_NAMED_PIPE;
1198 else /* regular file or directory */
1200 info->Characteristics |= FILE_DEVICE_IS_MOUNTED;
1202 /* check for floppy disk */
1203 if (major(st.st_dev) == FLOPPY_MAJOR)
1204 info->Characteristics |= FILE_REMOVABLE_MEDIA;
1206 if (fstatfs( fd, &stfs ) < 0) stfs.f_type = 0;
1207 switch (stfs.f_type)
1209 case 0x9660: /* iso9660 */
1210 case 0x15013346: /* udf */
1211 info->DeviceType = FILE_DEVICE_CD_ROM_FILE_SYSTEM;
1212 info->Characteristics |= FILE_REMOVABLE_MEDIA|FILE_READ_ONLY_DEVICE;
1213 break;
1214 case 0x6969: /* nfs */
1215 case 0x517B: /* smbfs */
1216 case 0x564c: /* ncpfs */
1217 info->DeviceType = FILE_DEVICE_NETWORK_FILE_SYSTEM;
1218 info->Characteristics |= FILE_REMOTE_DEVICE;
1219 break;
1220 case 0x01021994: /* tmpfs */
1221 case 0x28cd3d45: /* cramfs */
1222 case 0x1373: /* devfs */
1223 case 0x9fa0: /* procfs */
1224 info->DeviceType = FILE_DEVICE_VIRTUAL_DISK;
1225 break;
1226 default:
1227 info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
1228 break;
1231 #else
1232 static int warned;
1233 if (!warned++) FIXME( "device info not supported on this platform\n" );
1234 info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
1235 info->Characteristics = 0;
1236 #endif
1237 io->Information = sizeof(*info);
1238 io->u.Status = STATUS_SUCCESS;
1240 break;
1241 case FileFsAttributeInformation:
1242 FIXME( "%p: attribute info not supported\n", handle );
1243 break;
1244 case FileFsControlInformation:
1245 FIXME( "%p: control info not supported\n", handle );
1246 break;
1247 case FileFsFullSizeInformation:
1248 FIXME( "%p: full size info not supported\n", handle );
1249 break;
1250 case FileFsObjectIdInformation:
1251 FIXME( "%p: object id info not supported\n", handle );
1252 break;
1253 case FileFsMaximumInformation:
1254 FIXME( "%p: maximum info not supported\n", handle );
1255 break;
1256 default:
1257 io->u.Status = STATUS_INVALID_PARAMETER;
1258 break;
1260 wine_server_release_fd( handle, fd );
1261 return io->u.Status;
1265 /******************************************************************
1266 * NtFlushBuffersFile (NTDLL.@)
1268 * Flush any buffered data on an open file handle.
1270 * PARAMS
1271 * FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
1272 * IoStatusBlock [O] Receives information about the operation on return
1274 * RETURNS
1275 * Success: 0. IoStatusBlock is updated.
1276 * Failure: An NTSTATUS error code describing the error.
1278 NTSTATUS WINAPI NtFlushBuffersFile( HANDLE hFile, IO_STATUS_BLOCK* IoStatusBlock )
1280 NTSTATUS ret;
1281 HANDLE hEvent = NULL;
1283 SERVER_START_REQ( flush_file )
1285 req->handle = hFile;
1286 ret = wine_server_call( req );
1287 hEvent = reply->event;
1289 SERVER_END_REQ;
1290 if (!ret && hEvent)
1292 ret = NtWaitForSingleObject( hEvent, FALSE, NULL );
1293 NtClose( hEvent );
1295 return ret;
1298 /******************************************************************
1299 * NtLockFile (NTDLL.@)
1303 NTSTATUS WINAPI NtLockFile( HANDLE hFile, HANDLE lock_granted_event,
1304 PIO_APC_ROUTINE apc, void* apc_user,
1305 PIO_STATUS_BLOCK io_status, PLARGE_INTEGER offset,
1306 PLARGE_INTEGER count, ULONG* key, BOOLEAN dont_wait,
1307 BOOLEAN exclusive )
1309 NTSTATUS ret;
1310 HANDLE handle;
1311 BOOLEAN async;
1313 if (apc || io_status || key)
1315 FIXME("Unimplemented yet parameter\n");
1316 return STATUS_NOT_IMPLEMENTED;
1319 for (;;)
1321 SERVER_START_REQ( lock_file )
1323 req->handle = hFile;
1324 req->offset_low = offset->u.LowPart;
1325 req->offset_high = offset->u.HighPart;
1326 req->count_low = count->u.LowPart;
1327 req->count_high = count->u.HighPart;
1328 req->shared = !exclusive;
1329 req->wait = !dont_wait;
1330 ret = wine_server_call( req );
1331 handle = reply->handle;
1332 async = reply->overlapped;
1334 SERVER_END_REQ;
1335 if (ret != STATUS_PENDING)
1337 if (!ret && lock_granted_event) NtSetEvent(lock_granted_event, NULL);
1338 return ret;
1341 if (async)
1343 FIXME( "Async I/O lock wait not implemented, might deadlock\n" );
1344 if (handle) NtClose( handle );
1345 return STATUS_PENDING;
1347 if (handle)
1349 NtWaitForSingleObject( handle, FALSE, NULL );
1350 NtClose( handle );
1352 else
1354 LARGE_INTEGER time;
1356 /* Unix lock conflict, sleep a bit and retry */
1357 time.QuadPart = 100 * (ULONGLONG)10000;
1358 time.QuadPart = -time.QuadPart;
1359 NtDelayExecution( FALSE, &time );
1365 /******************************************************************
1366 * NtUnlockFile (NTDLL.@)
1370 NTSTATUS WINAPI NtUnlockFile( HANDLE hFile, PIO_STATUS_BLOCK io_status,
1371 PLARGE_INTEGER offset, PLARGE_INTEGER count,
1372 PULONG key )
1374 NTSTATUS status;
1376 TRACE( "%p %lx%08lx %lx%08lx\n",
1377 hFile, offset->u.HighPart, offset->u.LowPart, count->u.HighPart, count->u.LowPart );
1379 if (io_status || key)
1381 FIXME("Unimplemented yet parameter\n");
1382 return STATUS_NOT_IMPLEMENTED;
1385 SERVER_START_REQ( unlock_file )
1387 req->handle = hFile;
1388 req->offset_low = offset->u.LowPart;
1389 req->offset_high = offset->u.HighPart;
1390 req->count_low = count->u.LowPart;
1391 req->count_high = count->u.HighPart;
1392 status = wine_server_call( req );
1394 SERVER_END_REQ;
1395 return status;