diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c index d4c48277dc3..e7b0b77930d 100644 --- a/dlls/kernel32/tests/virtual.c +++ b/dlls/kernel32/tests/virtual.c @@ -901,26 +901,21 @@ static void test_NtAreMappedFilesTheSame(void) ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status ); status = pNtAreMappedFilesTheSame( ptr, (void *)0xdeadbeef ); - todo_wine ok( status == STATUS_CONFLICTING_ADDRESSES || status == STATUS_INVALID_ADDRESS, "NtAreMappedFilesTheSame returned %x\n", status ); status = pNtAreMappedFilesTheSame( ptr, NULL ); - todo_wine ok( status == STATUS_INVALID_ADDRESS, "NtAreMappedFilesTheSame returned %x\n", status ); - status = pNtAreMappedFilesTheSame( ptr, (void *)0x10000 ); - todo_wine + status = pNtAreMappedFilesTheSame( ptr, (void *)GetProcessHeap() ); ok( status == STATUS_CONFLICTING_ADDRESSES, "NtAreMappedFilesTheSame returned %x\n", status ); status = pNtAreMappedFilesTheSame( NULL, NULL ); - todo_wine ok( status == STATUS_INVALID_ADDRESS, "NtAreMappedFilesTheSame returned %x\n", status ); ptr2 = VirtualAlloc( NULL, 0x10000, MEM_COMMIT, PAGE_READWRITE ); ok( ptr2 != NULL, "VirtualAlloc error %u\n", GetLastError() ); status = pNtAreMappedFilesTheSame( ptr, ptr2 ); - todo_wine ok( status == STATUS_CONFLICTING_ADDRESSES, "NtAreMappedFilesTheSame returned %x\n", status ); VirtualFree( ptr2, 0, MEM_RELEASE ); @@ -933,11 +928,9 @@ static void test_NtAreMappedFilesTheSame(void) ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status ); status = pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"), GetModuleHandleA("kernel32.dll") ); - todo_wine ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status ); status = pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"), (char *)GetModuleHandleA("kernel32.dll") + 4096 ); - todo_wine ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status ); GetSystemDirectoryA( path, MAX_PATH ); @@ -961,6 +954,19 @@ static void test_NtAreMappedFilesTheSame(void) status = pNtAreMappedFilesTheSame( ptr, GetModuleHandleA("kernel32.dll") ); todo_wine ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status ); + + file2 = CreateFileA( path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 ); + ok( file2 != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() ); + map2 = CreateFileMappingA( file2, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL ); + ok( map2 != 0, "CreateFileMapping error %u\n", GetLastError() ); + ptr2 = MapViewOfFile( map2, FILE_MAP_READ, 0, 0, 0 ); + ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() ); + status = pNtAreMappedFilesTheSame( ptr, ptr2 ); + ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status ); + UnmapViewOfFile( ptr2 ); + CloseHandle( map2 ); + CloseHandle( file2 ); + UnmapViewOfFile( ptr ); CloseHandle( mapping ); diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c index 3ab3eb38ee0..a1faabf488e 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c @@ -1012,6 +1012,26 @@ static NTSTATUS allocate_dos_memory( struct file_view **view, unsigned int vprot } +/*********************************************************************** + * stat_mapping_file + * + * Stat the underlying file for a memory view. + */ +static NTSTATUS stat_mapping_file( struct file_view *view, struct stat *st ) +{ + NTSTATUS status; + int unix_fd, needs_close; + + if (!view->mapping) return STATUS_NOT_MAPPED_VIEW; + if (!(status = server_get_unix_fd( view->mapping, 0, &unix_fd, &needs_close, NULL, NULL ))) + { + if (fstat( unix_fd, st ) == -1) status = FILE_GetNtStatus(); + if (needs_close) close( unix_fd ); + } + return status; +} + + /*********************************************************************** * map_image * @@ -2780,7 +2800,32 @@ NTSTATUS WINAPI NtWriteVirtualMemory( HANDLE process, void *addr, const void *bu */ NTSTATUS WINAPI NtAreMappedFilesTheSame(PVOID addr1, PVOID addr2) { + struct file_view *view1, *view2; + struct stat st1, st2; + NTSTATUS status; + sigset_t sigset; + TRACE("%p %p\n", addr1, addr2); - return STATUS_NOT_SAME_DEVICE; + server_enter_uninterrupted_section( &csVirtual, &sigset ); + + view1 = VIRTUAL_FindView( addr1, 0 ); + view2 = VIRTUAL_FindView( addr2, 0 ); + + if (!view1 || !view2) + status = STATUS_INVALID_ADDRESS; + else if ((view1->protect & VPROT_VALLOC) || (view2->protect & VPROT_VALLOC)) + status = STATUS_CONFLICTING_ADDRESSES; + else if (!(view1->protect & VPROT_IMAGE) || !(view2->protect & VPROT_IMAGE)) + status = STATUS_NOT_SAME_DEVICE; + else if (view1 == view2) + status = STATUS_SUCCESS; + else if (!stat_mapping_file( view1, &st1 ) && !stat_mapping_file( view2, &st2 ) && + st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino) + status = STATUS_SUCCESS; + else + status = STATUS_NOT_SAME_DEVICE; + + server_leave_uninterrupted_section( &csVirtual, &sigset ); + return status; }