From: Bernd Herd codeberg@herdsoft.com
Renamed dlls/twain_32 to dlls/twaindsm thus creating twaindsm.dll as platform independent name for the Twain Data Source Manager as it is used on 64-Bit windows.
Create new dlls/twain_32 as a wrapper for 32-Bit Windows only that forwards all calls to the main implementation in twaindsm.dll.
Send the DG_CONTROL/DAT_ENTRYPOINT/MSG_SET before DG_CONTROL/DAT_IDENTITY/MSG_OPENDS so Twain 2.x aware data sources like sane.ds don't need to know the filename of the Twain DSM ro find the DSM entry point.
On 32-Bit Systems LoadLibrary for the twain_32.dll wrapper when opening the DS and it is not 2.x compliant. This makes sure it will find the DSM_Entry of twain_32.dll if it uses GetModuleHandle("twain_32.dll") to find the DLL. --- MAINTAINERS | 1 + configure | 6 ++- configure.ac | 5 +- dlls/{twain_32 => twaindsm}/Makefile.in | 3 +- dlls/{twain_32 => twaindsm}/dsm_ctrl.c | 47 +++++++++++++++---- dlls/{twain_32 => twaindsm}/resource.h | 0 dlls/{twain_32 => twaindsm}/tests/Makefile.in | 2 +- dlls/{twain_32 => twaindsm}/tests/dsm.c | 0 dlls/{twain_32 => twaindsm}/twain.rc | 0 dlls/{twain_32 => twaindsm}/twain32_main.c | 0 dlls/{twain_32 => twaindsm}/twain_i.h | 0 .../twain_32.spec => twaindsm/twaindsm.spec} | 0 12 files changed, 50 insertions(+), 14 deletions(-) rename dlls/{twain_32 => twaindsm}/Makefile.in (61%) rename dlls/{twain_32 => twaindsm}/dsm_ctrl.c (94%) rename dlls/{twain_32 => twaindsm}/resource.h (100%) rename dlls/{twain_32 => twaindsm}/tests/Makefile.in (64%) rename dlls/{twain_32 => twaindsm}/tests/dsm.c (100%) rename dlls/{twain_32 => twaindsm}/twain.rc (100%) rename dlls/{twain_32 => twaindsm}/twain32_main.c (100%) rename dlls/{twain_32 => twaindsm}/twain_i.h (100%) rename dlls/{twain_32/twain_32.spec => twaindsm/twaindsm.spec} (100%)
diff --git a/MAINTAINERS b/MAINTAINERS index c34abcecbc3..6167ff4464e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -325,6 +325,7 @@ F: dlls/uxtheme/ TWAIN P: Esme Povirk esme@codeweavers.com @madewokherd F: dlls/twain_32/ +F: dlls/twaindsm/ F: dlls/sane.ds/ F: dlls/gphoto2.ds/
diff --git a/configure b/configure index e3fd3140529..0942db1bf59 100755 --- a/configure +++ b/configure @@ -1457,6 +1457,7 @@ enable_tdi_sys enable_threadpoolwinrt enable_traffic enable_twain_32 +enable_twaindsm enable_twinapi_appcore enable_tzres enable_ucrtbase @@ -22278,6 +22279,8 @@ enable_msiexec=${enable_msiexec:-yes} enable_netsh=${enable_netsh:-yes} enable_regsvr32=${enable_regsvr32:-yes} enable_rundll32=${enable_rundll32:-yes} +enable_twaindsm=${enable_twaindsm:-yes} +enable_twain_32=${enable_twain_32:-i386}
enable_win16=${enable_win16:-i386} enable_w32skrnl=${enable_w32skrnl:-$enable_win16} @@ -23062,7 +23065,8 @@ wine_fn_config_makefile dlls/toolhelp.dll16 enable_win16 wine_fn_config_makefile dlls/traffic enable_traffic wine_fn_config_makefile dlls/twain.dll16 enable_win16 wine_fn_config_makefile dlls/twain_32 enable_twain_32 -wine_fn_config_makefile dlls/twain_32/tests enable_tests +wine_fn_config_makefile dlls/twaindsm enable_twaindsm +wine_fn_config_makefile dlls/twaindsm/tests enable_tests wine_fn_config_makefile dlls/twinapi.appcore enable_twinapi_appcore wine_fn_config_makefile dlls/twinapi.appcore/tests enable_tests wine_fn_config_makefile dlls/typelib.dll16 enable_win16 diff --git a/configure.ac b/configure.ac index a9db2abcce4..cf6d2953579 100644 --- a/configure.ac +++ b/configure.ac @@ -2420,6 +2420,8 @@ enable_msiexec=${enable_msiexec:-yes} enable_netsh=${enable_netsh:-yes} enable_regsvr32=${enable_regsvr32:-yes} enable_rundll32=${enable_rundll32:-yes} +enable_twaindsm=${enable_twaindsm:-yes} +enable_twain_32=${enable_twain_32:-i386}
dnl Disable Win16-related modules enable_win16=${enable_win16:-i386} @@ -3207,7 +3209,8 @@ WINE_CONFIG_MAKEFILE(dlls/toolhelp.dll16) WINE_CONFIG_MAKEFILE(dlls/traffic) WINE_CONFIG_MAKEFILE(dlls/twain.dll16) WINE_CONFIG_MAKEFILE(dlls/twain_32) -WINE_CONFIG_MAKEFILE(dlls/twain_32/tests) +WINE_CONFIG_MAKEFILE(dlls/twaindsm) +WINE_CONFIG_MAKEFILE(dlls/twaindsm/tests) WINE_CONFIG_MAKEFILE(dlls/twinapi.appcore) WINE_CONFIG_MAKEFILE(dlls/twinapi.appcore/tests) WINE_CONFIG_MAKEFILE(dlls/typelib.dll16) diff --git a/dlls/twain_32/Makefile.in b/dlls/twaindsm/Makefile.in similarity index 61% rename from dlls/twain_32/Makefile.in rename to dlls/twaindsm/Makefile.in index b4ac1e27729..ad8053803da 100644 --- a/dlls/twain_32/Makefile.in +++ b/dlls/twaindsm/Makefile.in @@ -1,4 +1,5 @@ -MODULE = twain_32.dll +MODULE = twaindsm.dll +IMPORTLIB = twaindsm IMPORTS = user32
SOURCES = \ diff --git a/dlls/twain_32/dsm_ctrl.c b/dlls/twaindsm/dsm_ctrl.c similarity index 94% rename from dlls/twain_32/dsm_ctrl.c rename to dlls/twaindsm/dsm_ctrl.c index 89e788f979d..c77f4f32b6b 100644 --- a/dlls/twain_32/dsm_ctrl.c +++ b/dlls/twaindsm/dsm_ctrl.c @@ -47,6 +47,11 @@ struct all_devices { static int nrdevices = 0; static struct all_devices *devices = NULL;
+#ifndef WIN64 +/* Instance-Handle of the twain_32.dll */ +HINSTANCE hinstTwain_32 = NULL; +#endif // !WIN64 + static void twain_add_onedriver(const WCHAR *dsname) { HMODULE hmod; @@ -276,6 +281,12 @@ TW_UINT16 TWAIN_CloseDS (pTW_IDENTITY pOrigin, TW_MEMREF pData) /* This causes crashes due to still open Windows, so leave out for now. * FreeLibrary (currentDS->hmod); */ +#ifndef WIN64 + if (!(pIdentity->SupportedGroups & DF_DS2)) { + FreeLibrary(hinstTwain_32); + } +#endif // !WIN64 + if (prevDS) prevDS->next = currentDS->next; else @@ -381,8 +392,34 @@ TW_UINT16 TWAIN_OpenDS (pTW_IDENTITY pOrigin, TW_MEMREF pData) } newSource->hmod = hmod; newSource->dsEntry = (DSENTRYPROC)GetProcAddress(hmod, "DS_Entry"); + if (!newSource->dsEntry) { + ERR("Failed to find DS_Entry() in TWAIN DS %s\n", debugstr_w(devices[i].modname)); + DSM_twCC = TWCC_OPERATIONERROR; + HeapFree(GetProcessHeap(), 0, newSource); + return TWRC_FAILURE; + } /* Assign id for the opened data source */ pIdentity->Id = DSM_sourceId ++; + /* Get the Identity of the new DS, so we know the SupportedGroups */ + if (TWRC_SUCCESS != newSource->dsEntry (NULL, DG_CONTROL, DAT_IDENTITY, MSG_GET, pIdentity)) { + DSM_twCC = TWCC_OPERATIONERROR; + HeapFree(GetProcessHeap(), 0, newSource); + DSM_sourceId--; + return TWRC_FAILURE; + } + /* Tell the source our entry points */ + if (pIdentity->SupportedGroups & DF_DS2) { + /* This makes sure that the DS knows the current address of our DSM_Entry + * function so there is no risk that it is using a stale copy. */ + newSource->dsEntry (pOrigin, DG_CONTROL, DAT_ENTRYPOINT, MSG_SET, (TW_ENTRYPOINT *) &_entrypoints); + } +#ifndef WIN64 + else { + /* DS is Version 1.x. Make sure twain_32.dll is loaded in case DS uses GetModuleHandle("twain_32") */ + hinstTwain_32 = LoadLibraryW(L"twain_32.dll"); + } +#endif // !WIN64 + /* Open the data source */ if (TWRC_SUCCESS != newSource->dsEntry (pOrigin, DG_CONTROL, DAT_IDENTITY, MSG_OPENDS, pIdentity)) { DSM_twCC = TWCC_OPERATIONERROR; HeapFree(GetProcessHeap(), 0, newSource); @@ -398,16 +435,6 @@ TW_UINT16 TWAIN_OpenDS (pTW_IDENTITY pOrigin, TW_MEMREF pData) newSource->event_window = NULL; activeSources = newSource; DSM_twCC = TWCC_SUCCESS; - - /* Tell the source our entry points */ - if (pIdentity->SupportedGroups & DF_DS2) { - /* This makes sure that the DS knows the current address of our DSM_Entry - * function so there is no risk that it is using a stale copy. - * The other entry points are also set for formal reasons, - * but are currently not used. - */ - newSource->dsEntry (pOrigin, DG_CONTROL, DAT_ENTRYPOINT, MSG_SET, (TW_ENTRYPOINT *) &_entrypoints); - } return TWRC_SUCCESS; }
diff --git a/dlls/twain_32/resource.h b/dlls/twaindsm/resource.h similarity index 100% rename from dlls/twain_32/resource.h rename to dlls/twaindsm/resource.h diff --git a/dlls/twain_32/tests/Makefile.in b/dlls/twaindsm/tests/Makefile.in similarity index 64% rename from dlls/twain_32/tests/Makefile.in rename to dlls/twaindsm/tests/Makefile.in index 13052327d7d..11cc60fef8b 100644 --- a/dlls/twain_32/tests/Makefile.in +++ b/dlls/twaindsm/tests/Makefile.in @@ -1,4 +1,4 @@ -TESTDLL = twain_32.dll +TESTDLL = twaindsm.dll IMPORTS = user32 gdi32
SOURCES = \ diff --git a/dlls/twain_32/tests/dsm.c b/dlls/twaindsm/tests/dsm.c similarity index 100% rename from dlls/twain_32/tests/dsm.c rename to dlls/twaindsm/tests/dsm.c diff --git a/dlls/twain_32/twain.rc b/dlls/twaindsm/twain.rc similarity index 100% rename from dlls/twain_32/twain.rc rename to dlls/twaindsm/twain.rc diff --git a/dlls/twain_32/twain32_main.c b/dlls/twaindsm/twain32_main.c similarity index 100% rename from dlls/twain_32/twain32_main.c rename to dlls/twaindsm/twain32_main.c diff --git a/dlls/twain_32/twain_i.h b/dlls/twaindsm/twain_i.h similarity index 100% rename from dlls/twain_32/twain_i.h rename to dlls/twaindsm/twain_i.h diff --git a/dlls/twain_32/twain_32.spec b/dlls/twaindsm/twaindsm.spec similarity index 100% rename from dlls/twain_32/twain_32.spec rename to dlls/twaindsm/twaindsm.spec