diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index d293b42ee77..4e28b1333f0 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -964,8 +964,7 @@ NTSTATUS WINAPI NtQueryVolumeInformationFile( HANDLE handle, PIO_STATUS_BLOCK io { int fd; - if ((io->u.Status = wine_server_handle_to_fd( handle, GENERIC_READ, - &fd, NULL, NULL )) != STATUS_SUCCESS) + if ((io->u.Status = wine_server_handle_to_fd( handle, 0, &fd, NULL, NULL )) != STATUS_SUCCESS) return io->u.Status; io->u.Status = STATUS_NOT_IMPLEMENTED; diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 97d0d6f6af2..01704c37f58 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -1227,6 +1227,9 @@ static NTSTATUS load_native_dll( LPCWSTR load_path, LPCWSTR name, HANDLE file, nt = RtlImageNtHeader( module ); + /* don't keep the file open if the mapping is from removable media */ + if (!VIRTUAL_HasMapping( module )) file = 0; + SERVER_START_REQ( load_dll ) { req->handle = file; diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 42af347fb3b..ce0efeb0a53 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -94,6 +94,7 @@ extern NTSTATUS FILE_GetNtStatus(void); typedef BOOL (*HANDLERPROC)(LPVOID, LPCVOID); extern BOOL VIRTUAL_SetFaultHandler(LPCVOID addr, HANDLERPROC proc, LPVOID arg); extern DWORD VIRTUAL_HandleFault(LPCVOID addr); +extern BOOL VIRTUAL_HasMapping( LPCVOID addr ); /* code pages */ extern int ntdll_umbstowcs(DWORD flags, const char* src, int srclen, WCHAR* dst, int dstlen); diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c index c8986d7f747..22898399e4d 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c @@ -43,6 +43,7 @@ #include "ntstatus.h" #include "thread.h" #include "winternl.h" +#include "winioctl.h" #include "wine/library.h" #include "wine/server.h" #include "wine/debug.h" @@ -877,6 +878,22 @@ DWORD VIRTUAL_HandleFault( LPCVOID addr ) return ret; } +/*********************************************************************** + * VIRTUAL_HasMapping + * + * Check if the specified view has an associated file mapping. + */ +BOOL VIRTUAL_HasMapping( LPCVOID addr ) +{ + FILE_VIEW *view; + BOOL ret = FALSE; + + RtlEnterCriticalSection( &csVirtual ); + if ((view = VIRTUAL_FindView( addr ))) ret = (view->mapping != 0); + RtlLeaveCriticalSection( &csVirtual ); + return ret; +} + /*********************************************************************** @@ -1434,6 +1451,8 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p ULONG commit_size, const LARGE_INTEGER *offset, ULONG *size_ptr, SECTION_INHERIT inherit, ULONG alloc_type, ULONG protect ) { + IO_STATUS_BLOCK io; + FILE_FS_DEVICE_INFORMATION device_info; NTSTATUS res; UINT size = 0; int flags = MAP_PRIVATE; @@ -1442,7 +1461,7 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p void *base, *ptr = (void *)-1, *ret; DWORD size_low, size_high, header_size, shared_size; HANDLE shared_file; - BOOL removable; + BOOL removable = FALSE; if (!is_current_process( process )) { @@ -1470,13 +1489,16 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p header_size = reply->header_size; shared_file = reply->shared_file; shared_size = reply->shared_size; - removable = reply->removable; } SERVER_END_REQ; if (res) return res; if ((res = wine_server_handle_to_fd( handle, 0, &unix_handle, NULL, NULL ))) return res; + if (NtQueryVolumeInformationFile( handle, &io, &device_info, sizeof(device_info), + FileFsDeviceInformation ) == STATUS_SUCCESS) + removable = device_info.Characteristics & FILE_REMOVABLE_MEDIA; + if (prot & VPROT_IMAGE) { if (shared_file) diff --git a/include/winternl.h b/include/winternl.h index 7595d295276..96f208f982f 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -1165,6 +1165,7 @@ NTSTATUS WINAPI NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS,PVOID,ULONG,P NTSTATUS WINAPI NtQuerySystemTime(PLARGE_INTEGER); NTSTATUS WINAPI NtQueryValueKey(HKEY,const UNICODE_STRING *,KEY_VALUE_INFORMATION_CLASS,void *,DWORD,DWORD *); NTSTATUS WINAPI NtQueryVirtualMemory(HANDLE,LPCVOID,MEMORY_INFORMATION_CLASS,PVOID,ULONG,ULONG*); +NTSTATUS WINAPI NtQueryVolumeInformationFile(HANDLE,PIO_STATUS_BLOCK,PVOID,ULONG,FS_INFORMATION_CLASS); void WINAPI NtRaiseException(PEXCEPTION_RECORD,PCONTEXT,BOOL); NTSTATUS WINAPI NtReadFile(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,PVOID,ULONG,PLARGE_INTEGER,PULONG); NTSTATUS WINAPI NtReadVirtualMemory(HANDLE,const void*,void*,SIZE_T,SIZE_T*); diff --git a/server/process.c b/server/process.c index 092755946e9..6afc0b294d0 100644 --- a/server/process.c +++ b/server/process.c @@ -1121,15 +1121,8 @@ DECL_HANDLER(load_dll) struct process_dll *dll; struct file *file = NULL; - if (req->handle) - { - if (!(file = get_file_obj( current->process, req->handle, GENERIC_READ ))) return; - if (is_file_removable( file )) /* don't keep the file open on removable media */ - { - release_object( file ); - file = NULL; - } - } + if (req->handle && !(file = get_file_obj( current->process, req->handle, GENERIC_READ ))) + return; if ((dll = process_load_dll( current->process, file, req->base, get_req_data(), get_req_data_size() )))