From f750086bc190d581cf3d25aa1300714dd4e2a136 Mon Sep 17 00:00:00 2001 From: Leo Yuriev Date: Tue, 18 Feb 2020 20:29:35 +0300 Subject: [PATCH] mdbx-windows: rework workaround for Wine. Resolves https://github.com/erthink/libmdbx/issues/83 in accordance with https://bugs.winehq.org/show_bug.cgi?id=48620 Change-Id: Ieb4385efdcd86c865184a783363cf6e90da14f61 --- src/elements/lck-windows.c | 65 +++++++++++++++++++++++--------------- src/elements/osal.c | 3 ++ src/elements/osal.h | 5 +++ 3 files changed, 48 insertions(+), 25 deletions(-) diff --git a/src/elements/lck-windows.c b/src/elements/lck-windows.c index 31dab38d..2d4c7d1a 100644 --- a/src/elements/lck-windows.c +++ b/src/elements/lck-windows.c @@ -733,7 +733,47 @@ MDBX_ReclaimVirtualMemory mdbx_ReclaimVirtualMemory; #endif /* MDBX_ALLOY */ static void mdbx_winnt_import(void) { + const HINSTANCE hNtdll = GetModuleHandleA("ntdll.dll"); + +#define GET_PROC_ADDR(dll, ENTRY) \ + mdbx_##ENTRY = (MDBX_##ENTRY)GetProcAddress(dll, #ENTRY) + + if (GetProcAddress(hNtdll, "wine_get_version")) { + assert(mdbx_RunningUnderWine()); + } else { + GET_PROC_ADDR(hNtdll, NtFsControlFile); + GET_PROC_ADDR(hNtdll, NtExtendSection); + assert(!mdbx_RunningUnderWine()); + } + const HINSTANCE hKernel32dll = GetModuleHandleA("kernel32.dll"); + GET_PROC_ADDR(hKernel32dll, GetFileInformationByHandleEx); + GET_PROC_ADDR(hKernel32dll, SetFileInformationByHandle); + GET_PROC_ADDR(hKernel32dll, GetTickCount64); + if (!mdbx_GetTickCount64) + mdbx_GetTickCount64 = stub_GetTickCount64; + if (!mdbx_RunningUnderWine()) { + GET_PROC_ADDR(hKernel32dll, GetVolumeInformationByHandleW); + GET_PROC_ADDR(hKernel32dll, GetFinalPathNameByHandleW); + GET_PROC_ADDR(hKernel32dll, PrefetchVirtualMemory); + } + +#if 0 /* LY: unused for now */ + if (!mdbx_RunningUnderWine()) { + GET_PROC_ADDR(hKernel32dll, DiscardVirtualMemory); + GET_PROC_ADDR(hKernel32dll, OfferVirtualMemory); + GET_PROC_ADDR(hKernel32dll, ReclaimVirtualMemory); + } + if (!mdbx_DiscardVirtualMemory) + mdbx_DiscardVirtualMemory = stub_DiscardVirtualMemory; + if (!mdbx_OfferVirtualMemory) + mdbx_OfferVirtualMemory = stub_OfferVirtualMemory; + if (!mdbx_ReclaimVirtualMemory) + mdbx_ReclaimVirtualMemory = stub_ReclaimVirtualMemory; +#endif /* unused for now */ + +#undef GET_PROC_ADDR + const MDBX_srwlock_function init = (MDBX_srwlock_function)GetProcAddress(hKernel32dll, "InitializeSRWLock"); if (init != NULL) { @@ -753,29 +793,4 @@ static void mdbx_winnt_import(void) { mdbx_srwlock_AcquireExclusive = stub_srwlock_AcquireExclusive; mdbx_srwlock_ReleaseExclusive = stub_srwlock_ReleaseExclusive; } - -#define GET_KERNEL32_PROC(ENTRY) \ - mdbx_##ENTRY = (MDBX_##ENTRY)GetProcAddress(hKernel32dll, #ENTRY) - GET_KERNEL32_PROC(GetFileInformationByHandleEx); - GET_KERNEL32_PROC(GetVolumeInformationByHandleW); - GET_KERNEL32_PROC(GetFinalPathNameByHandleW); - GET_KERNEL32_PROC(SetFileInformationByHandle); - GET_KERNEL32_PROC(PrefetchVirtualMemory); - GET_KERNEL32_PROC(GetTickCount64); - if (!mdbx_GetTickCount64) - mdbx_GetTickCount64 = stub_GetTickCount64; -#if 0 /* LY: unused for now */ - GET_KERNEL32_PROC(DiscardVirtualMemory); - if (!mdbx_DiscardVirtualMemory) - mdbx_DiscardVirtualMemory = stub_DiscardVirtualMemory; - GET_KERNEL32_PROC(OfferVirtualMemory); - GET_KERNEL32_PROC(ReclaimVirtualMemory); -#endif /* unused for now */ -#undef GET_KERNEL32_PROC - - const HINSTANCE hNtdll = GetModuleHandleA("ntdll.dll"); - mdbx_NtFsControlFile = - (MDBX_NtFsControlFile)GetProcAddress(hNtdll, "NtFsControlFile"); - mdbx_NtExtendSection = - (MDBX_NtExtendSection)GetProcAddress(hNtdll, "NtExtendSection"); } diff --git a/src/elements/osal.c b/src/elements/osal.c index 70d88565..761b0e93 100644 --- a/src/elements/osal.c +++ b/src/elements/osal.c @@ -985,6 +985,9 @@ MDBX_INTERNAL_FUNC int mdbx_check_fs_rdonly(mdbx_filehandle_t handle, static int mdbx_check_fs_local(mdbx_filehandle_t handle, int flags) { #if defined(_WIN32) || defined(_WIN64) + if (mdbx_RunningUnderWine() && !(flags & MDBX_EXCLUSIVE)) + return ERROR_NOT_CAPABLE /* workaround for Wine */; + if (GetFileType(handle) != FILE_TYPE_DISK) return ERROR_FILE_OFFLINE; diff --git a/src/elements/osal.h b/src/elements/osal.h index d2082a0f..ade7a6d1 100644 --- a/src/elements/osal.h +++ b/src/elements/osal.h @@ -760,6 +760,7 @@ MDBX_INTERNAL_FUNC int mdbx_rpid_clear(MDBX_env *env); MDBX_INTERNAL_FUNC int mdbx_rpid_check(MDBX_env *env, uint32_t pid); #if defined(_WIN32) || defined(_WIN64) + typedef union MDBX_srwlock { struct { long volatile readerCount; @@ -855,6 +856,10 @@ typedef NTSTATUS(NTAPI *MDBX_NtExtendSection)(IN HANDLE SectionHandle, IN PLARGE_INTEGER NewSectionSize); MDBX_INTERNAL_VAR MDBX_NtExtendSection mdbx_NtExtendSection; +static __inline bool mdbx_RunningUnderWine(void) { + return !mdbx_NtExtendSection; +} + #endif /* Windows */ /*----------------------------------------------------------------------------*/