forked from Mirrors/wine-wine
kernelbase: Implement ReOpenFile().
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47668 Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>feature/deterministic
parent
76238898fc
commit
c7019a8887
|
@ -59,6 +59,7 @@ static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)(LPCWSTR, PUNICODE_STRING, PW
|
||||||
static NTSTATUS (WINAPI *pRtlAnsiStringToUnicodeString)(PUNICODE_STRING, PCANSI_STRING, BOOLEAN);
|
static NTSTATUS (WINAPI *pRtlAnsiStringToUnicodeString)(PUNICODE_STRING, PCANSI_STRING, BOOLEAN);
|
||||||
static BOOL (WINAPI *pSetFileInformationByHandle)(HANDLE, FILE_INFO_BY_HANDLE_CLASS, void*, DWORD);
|
static BOOL (WINAPI *pSetFileInformationByHandle)(HANDLE, FILE_INFO_BY_HANDLE_CLASS, void*, DWORD);
|
||||||
static BOOL (WINAPI *pGetQueuedCompletionStatusEx)(HANDLE, OVERLAPPED_ENTRY*, ULONG, ULONG*, DWORD, BOOL);
|
static BOOL (WINAPI *pGetQueuedCompletionStatusEx)(HANDLE, OVERLAPPED_ENTRY*, ULONG, ULONG*, DWORD, BOOL);
|
||||||
|
static HANDLE (WINAPI *pReOpenFile)(HANDLE, DWORD, DWORD, DWORD);
|
||||||
static void (WINAPI *pRtlInitAnsiString)(PANSI_STRING,PCSZ);
|
static void (WINAPI *pRtlInitAnsiString)(PANSI_STRING,PCSZ);
|
||||||
static void (WINAPI *pRtlFreeUnicodeString)(PUNICODE_STRING);
|
static void (WINAPI *pRtlFreeUnicodeString)(PUNICODE_STRING);
|
||||||
static BOOL (WINAPI *pSetFileCompletionNotificationModes)(HANDLE, UCHAR);
|
static BOOL (WINAPI *pSetFileCompletionNotificationModes)(HANDLE, UCHAR);
|
||||||
|
@ -111,6 +112,7 @@ static void InitFunctionPointers(void)
|
||||||
pGetFinalPathNameByHandleW = (void *) GetProcAddress(hkernel32, "GetFinalPathNameByHandleW");
|
pGetFinalPathNameByHandleW = (void *) GetProcAddress(hkernel32, "GetFinalPathNameByHandleW");
|
||||||
pSetFileInformationByHandle = (void *) GetProcAddress(hkernel32, "SetFileInformationByHandle");
|
pSetFileInformationByHandle = (void *) GetProcAddress(hkernel32, "SetFileInformationByHandle");
|
||||||
pGetQueuedCompletionStatusEx = (void *) GetProcAddress(hkernel32, "GetQueuedCompletionStatusEx");
|
pGetQueuedCompletionStatusEx = (void *) GetProcAddress(hkernel32, "GetQueuedCompletionStatusEx");
|
||||||
|
pReOpenFile = (void *) GetProcAddress(hkernel32, "ReOpenFile");
|
||||||
pSetFileCompletionNotificationModes = (void *)GetProcAddress(hkernel32, "SetFileCompletionNotificationModes");
|
pSetFileCompletionNotificationModes = (void *)GetProcAddress(hkernel32, "SetFileCompletionNotificationModes");
|
||||||
pFindFirstStreamW = (void *)GetProcAddress(hkernel32, "FindFirstStreamW");
|
pFindFirstStreamW = (void *)GetProcAddress(hkernel32, "FindFirstStreamW");
|
||||||
}
|
}
|
||||||
|
@ -4410,6 +4412,104 @@ static void test_SetFileValidData(void)
|
||||||
DeleteFileA(filename);
|
DeleteFileA(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_ReOpenFile(void)
|
||||||
|
{
|
||||||
|
char path[MAX_PATH], filename[MAX_PATH], buffer[4];
|
||||||
|
HANDLE file, new;
|
||||||
|
unsigned int i;
|
||||||
|
DWORD size;
|
||||||
|
BOOL ret;
|
||||||
|
|
||||||
|
static const DWORD invalid_attributes[] =
|
||||||
|
{
|
||||||
|
FILE_ATTRIBUTE_ARCHIVE,
|
||||||
|
FILE_ATTRIBUTE_ENCRYPTED,
|
||||||
|
FILE_ATTRIBUTE_HIDDEN,
|
||||||
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
|
FILE_ATTRIBUTE_OFFLINE,
|
||||||
|
FILE_ATTRIBUTE_READONLY,
|
||||||
|
FILE_ATTRIBUTE_SYSTEM,
|
||||||
|
FILE_ATTRIBUTE_TEMPORARY,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const DWORD valid_attributes[] =
|
||||||
|
{
|
||||||
|
FILE_FLAG_BACKUP_SEMANTICS,
|
||||||
|
FILE_FLAG_NO_BUFFERING,
|
||||||
|
FILE_FLAG_OVERLAPPED,
|
||||||
|
FILE_FLAG_RANDOM_ACCESS,
|
||||||
|
FILE_FLAG_SEQUENTIAL_SCAN,
|
||||||
|
FILE_FLAG_WRITE_THROUGH,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!pReOpenFile)
|
||||||
|
{
|
||||||
|
win_skip("ReOpenFile() is not available\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GetTempPathA(sizeof(path), path);
|
||||||
|
GetTempFileNameA(path, "tst", 0, filename);
|
||||||
|
|
||||||
|
file = CreateFileA(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL,
|
||||||
|
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
|
||||||
|
ok(file != INVALID_HANDLE_VALUE, "failed to create file, error %u\n", GetLastError());
|
||||||
|
ret = WriteFile(file, "foo", 4, &size, NULL);
|
||||||
|
ok(ret, "failed to write file, error %u\n", GetLastError());
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(invalid_attributes); ++i)
|
||||||
|
{
|
||||||
|
SetLastError(0xdeadbeef);
|
||||||
|
new = pReOpenFile(file, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, invalid_attributes[i]);
|
||||||
|
ok(new == INVALID_HANDLE_VALUE, "got %p\n", new);
|
||||||
|
ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %u\n", GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
new = pReOpenFile(file, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0);
|
||||||
|
ok(new != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError());
|
||||||
|
|
||||||
|
ret = ReadFile(new, buffer, sizeof(buffer), &size, NULL);
|
||||||
|
ok(ret, "failed to read file, error %u\n", GetLastError());
|
||||||
|
ok(size == 4, "got size %u\n", size);
|
||||||
|
ok(!strcmp(buffer, "foo"), "got wrong data\n");
|
||||||
|
CloseHandle(new);
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(valid_attributes); ++i)
|
||||||
|
{
|
||||||
|
new = pReOpenFile(file, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, valid_attributes[i]);
|
||||||
|
ok(new != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError());
|
||||||
|
CloseHandle(new);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetLastError(0xdeadbeef);
|
||||||
|
new = pReOpenFile(file, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0);
|
||||||
|
ok(new == INVALID_HANDLE_VALUE, "got %p\n", new);
|
||||||
|
ok(GetLastError() == ERROR_SHARING_VIOLATION, "got error %u\n", GetLastError());
|
||||||
|
|
||||||
|
CloseHandle(file);
|
||||||
|
ret = DeleteFileA(filename);
|
||||||
|
ok(ret, "failed to delete file, error %u\n", GetLastError());
|
||||||
|
|
||||||
|
file = CreateNamedPipeA("\\\\.\\pipe\\test_pipe", PIPE_ACCESS_DUPLEX, 0, 1, 1000, 1000, 1000, NULL);
|
||||||
|
ok(file != INVALID_HANDLE_VALUE, "failed to create pipe, error %u\n", GetLastError());
|
||||||
|
|
||||||
|
new = pReOpenFile(file, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0);
|
||||||
|
todo_wine ok(new != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError());
|
||||||
|
|
||||||
|
ret = WriteFile(file, "foo", 4, &size, NULL);
|
||||||
|
todo_wine ok(ret, "failed to write file, error %u\n", GetLastError());
|
||||||
|
ret = ReadFile(new, buffer, sizeof(buffer), &size, NULL);
|
||||||
|
todo_wine ok(ret, "failed to read file, error %u\n", GetLastError());
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
ok(size == 4, "got size %u\n", size);
|
||||||
|
ok(!strcmp(buffer, "foo"), "got wrong data\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseHandle(new);
|
||||||
|
CloseHandle(file);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_WriteFileGather(void)
|
static void test_WriteFileGather(void)
|
||||||
{
|
{
|
||||||
char temp_path[MAX_PATH], filename[MAX_PATH];
|
char temp_path[MAX_PATH], filename[MAX_PATH];
|
||||||
|
@ -5483,4 +5583,5 @@ START_TEST(file)
|
||||||
test_file_readonly_access();
|
test_file_readonly_access();
|
||||||
test_find_file_stream();
|
test_find_file_stream();
|
||||||
test_SetFileTime();
|
test_SetFileTime();
|
||||||
|
test_ReOpenFile();
|
||||||
}
|
}
|
||||||
|
|
|
@ -432,6 +432,26 @@ HANDLE WINAPI DECLSPEC_HOTPATCH CreateFileA( LPCSTR name, DWORD access, DWORD sh
|
||||||
return CreateFileW( nameW, access, sharing, sa, creation, attributes, template );
|
return CreateFileW( nameW, access, sharing, sa, creation, attributes, template );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static UINT get_nt_file_options( DWORD attributes )
|
||||||
|
{
|
||||||
|
UINT options = 0;
|
||||||
|
|
||||||
|
if (attributes & FILE_FLAG_BACKUP_SEMANTICS)
|
||||||
|
options |= FILE_OPEN_FOR_BACKUP_INTENT;
|
||||||
|
else
|
||||||
|
options |= FILE_NON_DIRECTORY_FILE;
|
||||||
|
if (attributes & FILE_FLAG_DELETE_ON_CLOSE)
|
||||||
|
options |= FILE_DELETE_ON_CLOSE;
|
||||||
|
if (attributes & FILE_FLAG_NO_BUFFERING)
|
||||||
|
options |= FILE_NO_INTERMEDIATE_BUFFERING;
|
||||||
|
if (!(attributes & FILE_FLAG_OVERLAPPED))
|
||||||
|
options |= FILE_SYNCHRONOUS_IO_NONALERT;
|
||||||
|
if (attributes & FILE_FLAG_RANDOM_ACCESS)
|
||||||
|
options |= FILE_RANDOM_ACCESS;
|
||||||
|
if (attributes & FILE_FLAG_WRITE_THROUGH)
|
||||||
|
options |= FILE_WRITE_THROUGH;
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
* CreateFileW (kernelbase.@)
|
* CreateFileW (kernelbase.@)
|
||||||
|
@ -441,7 +461,6 @@ HANDLE WINAPI DECLSPEC_HOTPATCH CreateFileW( LPCWSTR filename, DWORD access, DWO
|
||||||
DWORD attributes, HANDLE template )
|
DWORD attributes, HANDLE template )
|
||||||
{
|
{
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
UINT options;
|
|
||||||
OBJECT_ATTRIBUTES attr;
|
OBJECT_ATTRIBUTES attr;
|
||||||
UNICODE_STRING nameW;
|
UNICODE_STRING nameW;
|
||||||
IO_STATUS_BLOCK io;
|
IO_STATUS_BLOCK io;
|
||||||
|
@ -543,25 +562,8 @@ HANDLE WINAPI DECLSPEC_HOTPATCH CreateFileW( LPCWSTR filename, DWORD access, DWO
|
||||||
|
|
||||||
/* now call NtCreateFile */
|
/* now call NtCreateFile */
|
||||||
|
|
||||||
options = 0;
|
|
||||||
if (attributes & FILE_FLAG_BACKUP_SEMANTICS)
|
|
||||||
options |= FILE_OPEN_FOR_BACKUP_INTENT;
|
|
||||||
else
|
|
||||||
options |= FILE_NON_DIRECTORY_FILE;
|
|
||||||
if (attributes & FILE_FLAG_DELETE_ON_CLOSE)
|
if (attributes & FILE_FLAG_DELETE_ON_CLOSE)
|
||||||
{
|
|
||||||
options |= FILE_DELETE_ON_CLOSE;
|
|
||||||
access |= DELETE;
|
access |= DELETE;
|
||||||
}
|
|
||||||
if (attributes & FILE_FLAG_NO_BUFFERING)
|
|
||||||
options |= FILE_NO_INTERMEDIATE_BUFFERING;
|
|
||||||
if (!(attributes & FILE_FLAG_OVERLAPPED))
|
|
||||||
options |= FILE_SYNCHRONOUS_IO_NONALERT;
|
|
||||||
if (attributes & FILE_FLAG_RANDOM_ACCESS)
|
|
||||||
options |= FILE_RANDOM_ACCESS;
|
|
||||||
if (attributes & FILE_FLAG_WRITE_THROUGH)
|
|
||||||
options |= FILE_WRITE_THROUGH;
|
|
||||||
attributes &= FILE_ATTRIBUTE_VALID_FLAGS;
|
|
||||||
|
|
||||||
attr.Length = sizeof(attr);
|
attr.Length = sizeof(attr);
|
||||||
attr.RootDirectory = 0;
|
attr.RootDirectory = 0;
|
||||||
|
@ -582,8 +584,9 @@ HANDLE WINAPI DECLSPEC_HOTPATCH CreateFileW( LPCWSTR filename, DWORD access, DWO
|
||||||
if (sa && sa->bInheritHandle) attr.Attributes |= OBJ_INHERIT;
|
if (sa && sa->bInheritHandle) attr.Attributes |= OBJ_INHERIT;
|
||||||
|
|
||||||
status = NtCreateFile( &ret, access | SYNCHRONIZE | FILE_READ_ATTRIBUTES, &attr, &io,
|
status = NtCreateFile( &ret, access | SYNCHRONIZE | FILE_READ_ATTRIBUTES, &attr, &io,
|
||||||
NULL, attributes, sharing, nt_disposition[creation - CREATE_NEW],
|
NULL, attributes & FILE_ATTRIBUTE_VALID_FLAGS, sharing,
|
||||||
options, NULL, 0 );
|
nt_disposition[creation - CREATE_NEW],
|
||||||
|
get_nt_file_options( attributes ), NULL, 0 );
|
||||||
if (status)
|
if (status)
|
||||||
{
|
{
|
||||||
if (vxd_name && vxd_name[0])
|
if (vxd_name && vxd_name[0])
|
||||||
|
@ -2550,10 +2553,41 @@ HANDLE WINAPI DECLSPEC_HOTPATCH OpenFileById( HANDLE handle, LPFILE_ID_DESCRIPTO
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ReOpenFile (kernelbase.@)
|
* ReOpenFile (kernelbase.@)
|
||||||
*/
|
*/
|
||||||
HANDLE WINAPI /* DECLSPEC_HOTPATCH */ ReOpenFile( HANDLE handle, DWORD access, DWORD sharing, DWORD flags )
|
HANDLE WINAPI DECLSPEC_HOTPATCH ReOpenFile( HANDLE handle, DWORD access, DWORD sharing, DWORD attributes )
|
||||||
{
|
{
|
||||||
FIXME( "(%p, %d, %d, %d): stub\n", handle, access, sharing, flags );
|
SECURITY_QUALITY_OF_SERVICE qos;
|
||||||
return INVALID_HANDLE_VALUE;
|
OBJECT_ATTRIBUTES attr;
|
||||||
|
UNICODE_STRING empty = { 0 };
|
||||||
|
IO_STATUS_BLOCK io;
|
||||||
|
NTSTATUS status;
|
||||||
|
HANDLE file;
|
||||||
|
|
||||||
|
TRACE("handle %p, access %#x, sharing %#x, attributes %#x.\n", handle, access, sharing, attributes);
|
||||||
|
|
||||||
|
if (attributes & 0x7ffff) /* FILE_ATTRIBUTE_* flags are invalid */
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes & FILE_FLAG_DELETE_ON_CLOSE)
|
||||||
|
access |= DELETE;
|
||||||
|
|
||||||
|
InitializeObjectAttributes( &attr, &empty, OBJ_CASE_INSENSITIVE, handle, NULL );
|
||||||
|
if (attributes & SECURITY_SQOS_PRESENT)
|
||||||
|
{
|
||||||
|
qos.Length = sizeof(qos);
|
||||||
|
qos.ImpersonationLevel = (attributes >> 16) & 0x3;
|
||||||
|
qos.ContextTrackingMode = attributes & SECURITY_CONTEXT_TRACKING ? SECURITY_DYNAMIC_TRACKING : SECURITY_STATIC_TRACKING;
|
||||||
|
qos.EffectiveOnly = (attributes & SECURITY_EFFECTIVE_ONLY) != 0;
|
||||||
|
attr.SecurityQualityOfService = &qos;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = NtCreateFile( &file, access | SYNCHRONIZE | FILE_READ_ATTRIBUTES, &attr, &io, NULL,
|
||||||
|
0, sharing, FILE_OPEN, get_nt_file_options( attributes ), NULL, 0 );
|
||||||
|
if (!set_ntstatus( status ))
|
||||||
|
return INVALID_HANDLE_VALUE;
|
||||||
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue