diff --git a/dlls/kernel32/file.c b/dlls/kernel32/file.c index cac1e980b3f..41abe49e30b 100644 --- a/dlls/kernel32/file.c +++ b/dlls/kernel32/file.c @@ -2601,6 +2601,57 @@ error: /* We get here if there was an error opening the file */ return HFILE_ERROR; } + +/*********************************************************************** + * OpenFileById (KERNEL32.@) + */ +HANDLE WINAPI OpenFileById( HANDLE handle, LPFILE_ID_DESCRIPTOR id, DWORD access, + DWORD share, LPSECURITY_ATTRIBUTES sec_attr, DWORD flags ) +{ + UINT options; + HANDLE result; + OBJECT_ATTRIBUTES attr; + NTSTATUS status; + IO_STATUS_BLOCK io; + UNICODE_STRING objectName; + + if (!id) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return INVALID_HANDLE_VALUE; + } + + options = FILE_OPEN_BY_FILE_ID; + if (flags & FILE_FLAG_BACKUP_SEMANTICS) + options |= FILE_OPEN_FOR_BACKUP_INTENT; + else + options |= FILE_NON_DIRECTORY_FILE; + if (flags & FILE_FLAG_NO_BUFFERING) options |= FILE_NO_INTERMEDIATE_BUFFERING; + if (!(flags & FILE_FLAG_OVERLAPPED)) options |= FILE_SYNCHRONOUS_IO_NONALERT; + if (flags & FILE_FLAG_RANDOM_ACCESS) options |= FILE_RANDOM_ACCESS; + flags &= FILE_ATTRIBUTE_VALID_FLAGS; + + objectName.Length = sizeof(ULONGLONG); + objectName.Buffer = (WCHAR *)&id->u.FileId; + attr.Length = sizeof(attr); + attr.RootDirectory = handle; + attr.Attributes = 0; + attr.ObjectName = &objectName; + attr.SecurityDescriptor = sec_attr ? sec_attr->lpSecurityDescriptor : NULL; + attr.SecurityQualityOfService = NULL; + if (sec_attr && sec_attr->bInheritHandle) attr.Attributes |= OBJ_INHERIT; + + status = NtCreateFile( &result, access, &attr, &io, NULL, flags, + share, OPEN_EXISTING, options, NULL, 0 ); + if (status != STATUS_SUCCESS) + { + SetLastError( RtlNtStatusToDosError( status ) ); + return INVALID_HANDLE_VALUE; + } + return result; +} + + /*********************************************************************** * K32EnumDeviceDrivers (KERNEL32.@) */ diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec index 57f7aff0e67..b7efa0f0a3a 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -886,6 +886,7 @@ @ stdcall OpenEventA(long long str) @ stdcall OpenEventW(long long wstr) @ stdcall OpenFile(str ptr long) +@ stdcall OpenFileById(long ptr long long ptr long) @ stdcall OpenFileMappingA(long long str) @ stdcall OpenFileMappingW(long long wstr) @ stdcall OpenJobObjectA(long long str) diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c index 6cc79c0fff1..11e0044d63e 100644 --- a/dlls/kernel32/tests/file.c +++ b/dlls/kernel32/tests/file.c @@ -3419,7 +3419,6 @@ static void test_OpenFileById(void) SetLastError(0xdeadbeef); handle = pOpenFileById(directory, NULL, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, 0); - todo_wine ok(handle == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_PARAMETER, "OpenFileById: expected ERROR_INVALID_PARAMETER, got error %u.\n", GetLastError()); @@ -3427,7 +3426,6 @@ static void test_OpenFileById(void) fileIdDescr.Type = FileIdType; U(fileIdDescr).FileId = bothDirInfo->FileId; handle = pOpenFileById(directory, &fileIdDescr, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, 0); - todo_wine ok(handle != INVALID_HANDLE_VALUE, "OpenFileById: failed to open the file, got error %u.\n", GetLastError()); ret = ReadFile(handle, buffer, sizeof(buffer), &count, NULL);