From 81e4a0f6f30a6196de4a36496461be257b6d9885 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Fri, 14 Mar 2008 20:29:00 +0100 Subject: [PATCH] ntdll: Implemented NtReadFileScatter. --- dlls/ntdll/file.c | 85 +++++++++++++++++++++++++++++++++++++++++++ dlls/ntdll/ntdll.spec | 8 ++-- include/winternl.h | 2 +- 3 files changed, 90 insertions(+), 5 deletions(-) diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index c7b944b6a9b..3b6783271df 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -715,6 +715,91 @@ err: return status; } + +/****************************************************************************** + * NtReadFileScatter [NTDLL.@] + * ZwReadFileScatter [NTDLL.@] + */ +NTSTATUS WINAPI NtReadFileScatter( HANDLE file, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user, + PIO_STATUS_BLOCK io_status, FILE_SEGMENT_ELEMENT *segments, + ULONG length, PLARGE_INTEGER offset, PULONG key ) +{ + size_t page_size = getpagesize(); + int result, unix_handle, needs_close; + unsigned int options; + NTSTATUS status; + ULONG pos = 0, total = 0; + enum server_fd_type type; + ULONG_PTR cvalue = apc ? 0 : (ULONG_PTR)apc_user; + + TRACE( "(%p,%p,%p,%p,%p,%p,0x%08x,%p,%p),partial stub!\n", + file, event, apc, apc_user, io_status, segments, length, offset, key); + + if (length % page_size) return STATUS_INVALID_PARAMETER; + if (!io_status) return STATUS_ACCESS_VIOLATION; + + status = server_get_unix_fd( file, FILE_READ_DATA, &unix_handle, + &needs_close, &type, &options ); + if (status) return status; + + if ((type != FD_TYPE_FILE) || + (options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)) || + !(options & FILE_NO_INTERMEDIATE_BUFFERING)) + { + status = STATUS_INVALID_PARAMETER; + goto error; + } + + while (length) + { + if (offset && offset->QuadPart != (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */) + result = pread( unix_handle, (char *)segments->Buffer + pos, + page_size - pos, offset->QuadPart + total ); + else + result = read( unix_handle, (char *)segments->Buffer + pos, page_size - pos ); + + if (result == -1) + { + if (errno == EINTR) continue; + status = FILE_GetNtStatus(); + break; + } + if (!result) + { + status = STATUS_END_OF_FILE; + break; + } + total += result; + length -= result; + if ((pos += result) == page_size) + { + pos = 0; + segments++; + } + } + + if (cvalue) NTDLL_AddCompletion( file, cvalue, status, total ); + + error: + if (needs_close) close( unix_handle ); + if (status == STATUS_SUCCESS) + { + io_status->u.Status = status; + io_status->Information = total; + TRACE("= SUCCESS (%u)\n", total); + if (event) NtSetEvent( event, NULL ); + if (apc) NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)apc, + (ULONG_PTR)apc_user, (ULONG_PTR)io_status, 0 ); + } + else + { + TRACE("= 0x%08x\n", status); + if (status != STATUS_PENDING && event) NtResetEvent( event, NULL ); + } + return status; +} + + /*********************************************************************** * FILE_AsyncWriteService (INTERNAL) */ diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 93851538dff..ebb65f4da50 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -275,8 +275,8 @@ @ stdcall NtQueueApcThread(long ptr long long long) @ stdcall NtRaiseException(ptr ptr long) @ stub NtRaiseHardError -@ stdcall NtReadFile(long long long long long long long long long) -@ stub NtReadFileScatter +@ stdcall NtReadFile(long long ptr ptr ptr ptr long ptr ptr) +@ stdcall NtReadFileScatter(long long ptr ptr ptr ptr long ptr ptr) @ stub NtReadRequestData @ stdcall NtReadVirtualMemory(long ptr ptr long ptr) @ stub NtRegisterNewDevice @@ -1118,8 +1118,8 @@ @ stdcall ZwQueueApcThread(long ptr long long long) NtQueueApcThread @ stdcall ZwRaiseException(ptr ptr long) NtRaiseException @ stub ZwRaiseHardError -@ stdcall ZwReadFile(long long long long long long long long long) NtReadFile -# @ stub ZwReadFileScatter +@ stdcall ZwReadFile(long long ptr ptr ptr ptr long ptr ptr) NtReadFile +@ stdcall ZwReadFileScatter(long long ptr ptr ptr ptr long ptr ptr) NtReadFileScatter @ stub ZwReadRequestData @ stdcall ZwReadVirtualMemory(long ptr ptr long ptr) NtReadVirtualMemory @ stub ZwRegisterNewDevice diff --git a/include/winternl.h b/include/winternl.h index d8d64694400..5b542957b85 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -1987,7 +1987,7 @@ NTSYSAPI NTSTATUS WINAPI NtQueryVolumeInformationFile(HANDLE,PIO_STATUS_BLOCK,P NTSYSAPI NTSTATUS WINAPI NtRaiseException(PEXCEPTION_RECORD,PCONTEXT,BOOL); NTSYSAPI NTSTATUS WINAPI NtRaiseHardError(NTSTATUS,ULONG,PUNICODE_STRING,PVOID*,HARDERROR_RESPONSE_OPTION,PHARDERROR_RESPONSE); NTSYSAPI NTSTATUS WINAPI NtReadFile(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,PVOID,ULONG,PLARGE_INTEGER,PULONG); -NTSYSAPI NTSTATUS WINAPI NtReadFileScatter(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,FILE_SEGMENT_ELEMENT,ULONG,PLARGE_INTEGER,PULONG); +NTSYSAPI NTSTATUS WINAPI NtReadFileScatter(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,FILE_SEGMENT_ELEMENT*,ULONG,PLARGE_INTEGER,PULONG); NTSYSAPI NTSTATUS WINAPI NtReadRequestData(HANDLE,PLPC_MESSAGE,ULONG,PVOID,ULONG,PULONG); NTSYSAPI NTSTATUS WINAPI NtReadVirtualMemory(HANDLE,const void*,void*,SIZE_T,SIZE_T*); NTSYSAPI NTSTATUS WINAPI NtRegisterThreadTerminatePort(HANDLE);