add dsm component and adjust directories
This commit is contained in:
parent
05788d91f1
commit
8fc62ad16f
7
build.sh
7
build.sh
|
@ -220,10 +220,13 @@ echo Make your choice, plz:
|
|||
|
||||
read choice
|
||||
if [ "$choice" == "y" ] || [ "$choice" == "Y" ]; then
|
||||
cd ../code_device/twain
|
||||
cd ../code_device/twain/dsm
|
||||
./build.sh $docpath $cpu
|
||||
|
||||
cd ../ds
|
||||
for pid in ${devpids[@]}
|
||||
do
|
||||
./build.sh $oem $pid
|
||||
./build.sh $oem $pid "nocopy"
|
||||
done
|
||||
cd ../
|
||||
fi
|
||||
|
|
|
@ -103,6 +103,7 @@ extern "C"
|
|||
utils::to_log(LOG_LEVEL_DEBUG, "Module device: [%u.%u.%u.%u] - %s\n", VERSION_MAJOR, VERSION_MINOR, VERSION_YEAR, GET_BUILD_VER, scanner.c_str());
|
||||
utils::to_log(LOG_LEVEL_DEBUG, "Module sane : [%s] - %s\n", g_sane_ver.c_str(), sane.c_str());
|
||||
utils::to_log(LOG_LEVEL_DEBUG, "Module exe : %s\n", (pe + name).c_str());
|
||||
utils::to_log(LOG_LEVEL_DEBUG, "Current Path : %s\n", utils::get_command_result("pwd").c_str());
|
||||
|
||||
if (lang_initialize() == -1)
|
||||
{
|
||||
|
|
|
@ -10,8 +10,8 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -fvisibility=hidden")
|
|||
aux_source_directory(${PROJECT_SOURCE_DIR} DIR_SRCS)
|
||||
# add_subdirectory(twain)
|
||||
file(GLOB DIR_HEADS "${PROJECT_SOURCE_DIR}/*.h" "${PROJECT_SOURCE_DIR}/*.hpp" "${PROJECT_SOURCE_DIR}/*.cpp"
|
||||
"${PROJECT_SOURCE_DIR}/../sdk/hginclude/*.h"
|
||||
"${PROJECT_SOURCE_DIR}/../sdk/hginclude/*.cpp"
|
||||
"${PROJECT_SOURCE_DIR}/../../sdk/hginclude/*.h"
|
||||
"${PROJECT_SOURCE_DIR}/../../sdk/hginclude/*.cpp"
|
||||
)
|
||||
|
||||
set(DIR_SRCS ${DIR_SRCS} ${DIR_HEADS})
|
||||
|
@ -24,20 +24,20 @@ link_libraries(dl)
|
|||
# )
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR}
|
||||
${PROJECT_SOURCE_DIR}/../sdk/hginclude
|
||||
${PROJECT_SOURCE_DIR}/../../sdk/include
|
||||
${PROJECT_SOURCE_DIR}/../../sdk/include/huagao
|
||||
${PROJECT_SOURCE_DIR}/../../sdk/include/twain
|
||||
${PROJECT_SOURCE_DIR}/../../sdk/include/twain/twpp
|
||||
${PROJECT_SOURCE_DIR}/../../sdk/hginclude
|
||||
${PROJECT_SOURCE_DIR}/../../../sdk/include
|
||||
${PROJECT_SOURCE_DIR}/../../../sdk/include/huagao
|
||||
${PROJECT_SOURCE_DIR}/../../../sdk/include/twain
|
||||
${PROJECT_SOURCE_DIR}/../../../sdk/include/twain/twpp
|
||||
)
|
||||
|
||||
target_link_directories(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR}
|
||||
${PROJECT_SOURCE_DIR}/../../release/kylin/x86_64)
|
||||
${PROJECT_SOURCE_DIR}/../../../release/kylin/x86_64)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||
pthread
|
||||
usb-1.0
|
||||
)
|
||||
|
||||
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/../../release/kylin/x86_64)
|
||||
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/../../../release/kylin/x86_64)
|
||||
|
|
@ -60,11 +60,11 @@ echo origin path is $origin_dir
|
|||
if [ -f ../../build/twain/Makefile ]; then
|
||||
echo ""
|
||||
else
|
||||
mkdir ../../build
|
||||
mkdir ../../build/twain
|
||||
mkdir ../../../build
|
||||
mkdir ../../../build/twainds
|
||||
fi
|
||||
|
||||
cd ../../build/twain
|
||||
cd ../../../build/twainds
|
||||
echo building path is $(pwd)
|
||||
rm -rf ./*
|
||||
cmake $origin_dir
|
||||
|
@ -81,8 +81,8 @@ else
|
|||
mv ../../release/${sys}/${cpu}/lib${oem}twain.so ../../release/${sys}/${cpu}/lib${oem}twain${pid}.ds
|
||||
fi
|
||||
|
||||
if [ -f ../../code_device/twain/CMakeLists.txtbkp ]; then
|
||||
mv ../../code_device/twain/CMakeLists.txtbkp ../../code_device/twain/CMakeLists.txt
|
||||
if [ -f ../../code_device/twain/ds/CMakeLists.txtbkp ]; then
|
||||
mv ../../code_device/twain/ds/CMakeLists.txtbkp ../../code_device/twain/ds/CMakeLists.txt
|
||||
pwd
|
||||
fi
|
||||
|
||||
|
@ -91,6 +91,7 @@ cd $origin_dir
|
|||
exit $err
|
||||
|
||||
|
||||
# echo -------copy DS to system directory ...-------
|
||||
# sudo cp ../../release/kylin/x86_64/libhgtwain.so /usr/local/lib/twain/libhgtwain.so.ds
|
||||
|
||||
if [ "$3" == "" ]; then
|
||||
echo -------copy DS to system directory ...-------
|
||||
sudo cp ../../../release/${sys}/${cpu}/lib${oem}twain${pid}.ds /usr/local/lib/twain/
|
||||
fi
|
|
@ -9,7 +9,7 @@
|
|||
#include <string>
|
||||
#include <thread>
|
||||
#include "twpp.hpp"
|
||||
#include "../sdk/hginclude/utils.h"
|
||||
#include "../../sdk/hginclude/utils.h"
|
||||
#include "s2t_api.h"
|
||||
|
||||
namespace std {
|
|
@ -1,6 +1,6 @@
|
|||
#include "sane_helper.h"
|
||||
#include "huagao/brand.h"
|
||||
#include "../sdk/hginclude/utils.h"
|
||||
#include "../../sdk/hginclude/utils.h"
|
||||
|
||||
|
||||
#include <string.h>
|
|
@ -13,7 +13,7 @@
|
|||
#include <twain_user/twainui.h>
|
||||
#include <huagao/brand.h>
|
||||
#include "sane_helper.h"
|
||||
#include "../sdk/hginclude/utils.h"
|
||||
#include "../../sdk/hginclude/utils.h"
|
||||
|
||||
#define START_SCAN_IN_THREAD
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
# this is just a basic CMakeLists.txt, for more information see the cmake manpage...
|
||||
|
||||
cmake_minimum_required(VERSION 2.4)
|
||||
|
||||
SET(OSTARGET "${OSTARGET}" CACHE STRING "woof")
|
||||
|
||||
IF(EXISTS "/bin/uname")
|
||||
EXEC_PROGRAM("/bin/uname" ARGS -p OUTPUT_VARIABLE CMAKE_SYSTEM_PROCESSOR)
|
||||
ELSEIF("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
|
||||
SET(CMAKE_SYSTEM_PROCESSOR "x86_64" CACHE STRING "woof" FORCE)
|
||||
ELSE()
|
||||
SET(CMAKE_SYSTEM_PROCESSOR "x86" CACHE STRING "woof" FORCE)
|
||||
ENDIF(EXISTS "/bin/uname")
|
||||
|
||||
IF("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "mips64")
|
||||
message(STATUS "Detected processor: ${CMAKE_SYSTEM_PROCESSOR} building ${OSTARGET}")
|
||||
ELSE()
|
||||
message(STATUS "Detected processor: ${CMAKE_SYSTEM_PROCESSOR}")
|
||||
ENDIF("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "mips64")
|
||||
|
||||
# Setup the install prefix, if it's not already defined
|
||||
IF(NOT CMAKE_INSTALL_PREFIX)
|
||||
SET(CMAKE_INSTALL_PREFIX "/usr/local")
|
||||
ENDIF(NOT CMAKE_INSTALL_PREFIX)
|
||||
|
||||
# Setup the build prefix, if it's not already defined
|
||||
IF(NOT CMAKE_BUILD_TYPE)
|
||||
SET(CMAKE_BUILD_TYPE "Release")
|
||||
ENDIF(NOT CMAKE_BUILD_TYPE)
|
||||
|
||||
#add definitions, compiler switches, etc.
|
||||
IF(APPLE)
|
||||
SET(CMAKE_OSX_ARCHITECTURES "i386;x86_64")
|
||||
ADD_DEFINITIONS(-Wall -Wextra -Werror -isysroot /Developer/SDKs/MacOSX10.6.sdk -mmacosx-version-min=10.6 -fexceptions -fPIC)
|
||||
ELSEIF("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "mips64")
|
||||
IF("${OSTARGET}" STREQUAL "mips64el")
|
||||
ADD_DEFINITIONS(-Wall -Wextra -Werror)
|
||||
ELSE()
|
||||
ADD_DEFINITIONS(-Wall -Wextra -Werror -march=from-abi -mabi=32)
|
||||
ENDIF()
|
||||
ELSE()
|
||||
ADD_DEFINITIONS(-Wall -Wextra -Werror -Wno-implicit-fallthrough)
|
||||
ENDIF(APPLE)
|
||||
|
||||
#let's not be sharing our symbols...
|
||||
IF(APPLE)
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS "-Wl,-ldl -Wl,-framework,CoreServices -Wl,-framework,Foundation" CACHE STRING "woof" FORCE)
|
||||
ELSEIF("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "mips64")
|
||||
IF("${OSTARGET}" STREQUAL "mips64el")
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS "-Wl,-Bsymbolic -Wl,--no-undefined -Wl,-ldl" CACHE STRING "woof" FORCE)
|
||||
ELSE()
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS "-Wl,-Bsymbolic -Wl,--no-undefined -Wl,-ldl -march=from-abi -mabi=32" CACHE STRING "woof" FORCE)
|
||||
ENDIF()
|
||||
ELSE()
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS "-Wl,-Bsymbolic -Wl,--no-undefined -Wl,-ldl" CACHE STRING "woof" FORCE)
|
||||
ENDIF(APPLE)
|
||||
|
||||
#project name
|
||||
PROJECT(twaindsm)
|
||||
|
||||
#project version
|
||||
SET(${PROJECT_NAME}_MAJOR_VERSION 2)
|
||||
SET(${PROJECT_NAME}_MINOR_VERSION 5)
|
||||
SET(${PROJECT_NAME}_PATCH_LEVEL 0)
|
||||
|
||||
#build a shared library
|
||||
ADD_LIBRARY(twaindsm SHARED dsm.cpp apps.cpp log.cpp)
|
||||
target_link_libraries(twaindsm dl)
|
||||
|
||||
#
|
||||
SET_TARGET_PROPERTIES(twaindsm PROPERTIES
|
||||
VERSION ${${PROJECT_NAME}_MAJOR_VERSION}.${${PROJECT_NAME}_MINOR_VERSION}.${${PROJECT_NAME}_PATCH_LEVEL}
|
||||
SOVERSION ${${PROJECT_NAME}_MAJOR_VERSION})
|
||||
|
||||
#add an install target here
|
||||
INSTALL(FILES twain.h DESTINATION include)
|
||||
INSTALL(TARGETS twaindsm
|
||||
LIBRARY DESTINATION lib
|
||||
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
|
||||
|
|
@ -0,0 +1,319 @@
|
|||
This file has the translations for the User Selection dialog in the Data Source Manager (DSM), it's
|
||||
saved as UTF-8, so if you're running a savvy editor with a suitable font you should see the proper
|
||||
characters under the "Translation" heading.
|
||||
|
||||
In terms of the TWLG_* values, mappings default to the primary (ex: English, French, Spanish). There
|
||||
is support to have different tranlations for the secondaries, if needed (ex: French vs French-Belgian
|
||||
vs French=Swiss).
|
||||
|
||||
Some languages may not be fully translated, in that case English fills in the missing fields. The
|
||||
idea is that a little translating is better than none at all.
|
||||
|
||||
Many of these translations come from a version of the DSM released for Microsoft Windows 98. The
|
||||
words "Select Source" and "Sources:" have been consistently used. If any translator feels that the
|
||||
words "Select Driver" and "Drivers:" would be clearer or more appropriate, please go to the TWAIN
|
||||
Working Group website, and from there go to the forums and submit your recommendation.
|
||||
|
||||
There are no translations for any languages that require the dialog box to be arranged from
|
||||
right to left. If such a translation is submitted, please make mention that the switch needs to
|
||||
be done as well.
|
||||
|
||||
Note: It's not always clear what the sublang for a language should be, which is one reason the DSM
|
||||
will fail over to just the primary if it can't make a match.
|
||||
|
||||
|
||||
|
||||
Language Translation UTF-8
|
||||
-----------------------------------------------------------------------------------------------------------
|
||||
|
||||
TWLG_AFRIKAANS, ANSI_CHARSET, MAKELANGID(LANG_AFRIKAANS,SUBLANG_NEUTRAL)
|
||||
Select Source
|
||||
Sources:
|
||||
Select
|
||||
Cancel Kanselleer \x4b\x61\x6e\x73\x65\x6c\x6c\x65\x65\x72
|
||||
|
||||
|
||||
TWLG_ALBANIA, EASTEUROPE_CHARSET, MAKELANGID(LANG_ALBANIAN,SUBLANG_NEUTRAL)
|
||||
TWLG_ARABIC, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_NEUTRAL)
|
||||
TWLG_ARABIC_ALGERIA, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_ALGERIA)
|
||||
TWLG_ARABIC_BAHRAIN, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_BAHRAIN)
|
||||
TWLG_ARABIC_EGYPT, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_EGYPT)
|
||||
TWLG_ARABIC_IRAQ, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_IRAQ)
|
||||
TWLG_ARABIC_JORDAN, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_JORDAN)
|
||||
TWLG_ARABIC_KUWAIT, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_KUWAIT)
|
||||
TWLG_ARABIC_LEBANON, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_LEBANON)
|
||||
TWLG_ARABIC_LIBYA, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_LIBYA)
|
||||
TWLG_ARABIC_MOROCCO, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_MOROCCO)
|
||||
TWLG_ARABIC_OMAN, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_OMAN)
|
||||
TWLG_ARABIC_QATAR, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_QATAR)
|
||||
TWLG_ARABIC_SAUDIARABIA, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_SAUDI_ARABIA)
|
||||
TWLG_ARABIC_SYRIA, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_SYRIA)
|
||||
TWLG_ARABIC_TUNISIA, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_TUNISIA)
|
||||
TWLG_ARABIC_UAE, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_UAE)
|
||||
TWLG_ARABIC_YEMEN, ARABIC_CHARSET, MAKELANGID(LANG_ARABIC,SUBLANG_ARABIC_YEMEN)
|
||||
TWLG_ASSAMESE, ANSI_CHARSET, MAKELANGID(LANG_ASSAMESE,SUBLANG_NEUTRAL)
|
||||
|
||||
|
||||
TWLG_BASQUE, ANSI_CHARSET, MAKELANGID(LANG_BASQUE,SUBLANG_NEUTRAL)
|
||||
Select Source
|
||||
Sources:
|
||||
Select
|
||||
Cancel Utzi \x55\x74\x7a\x69
|
||||
|
||||
|
||||
TWLG_BENGALI, ANSI_CHARSET, MAKELANGID(LANG_BENGALI,SUBLANG_NEUTRAL)
|
||||
TWLG_BIHARI, 0, 0
|
||||
TWLG_BODO, 0, 0
|
||||
TWLG_BULGARIAN, RUSSIAN_CHARSET, MAKELANGID(LANG_BULGARIAN,SUBLANG_NEUTRAL)
|
||||
TWLG_BYELORUSSIAN, RUSSIAN_CHARSET, MAKELANGID(LANG_BELARUSIAN,SUBLANG_NEUTRAL)
|
||||
|
||||
|
||||
TWLG_CATALAN ANSI_CHARSET, MAKELANGID(LANG_CATALAN,SUBLANG_NEUTRAL)
|
||||
Select Source
|
||||
Sources:
|
||||
Select
|
||||
Cancel Cancel·la \x43\x61\x6e\x63\x65\x6c\xc2\xb7\x6c\x61
|
||||
|
||||
|
||||
TWLG_CHINESE, GB2312_CHARSET, MAKELANGID(LANG_CHINESE,SUBLANG_NEUTRAL)
|
||||
TWLG_CHINESE_PRC, GB2312_CHARSET, MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED)
|
||||
TWLG_CHINESE_SIMPLIFIED, GB2312_CHARSET, MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED)
|
||||
TWLG_CHINESE_SINGAPORE, GB2312_CHARSET, MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED)
|
||||
Select Source 选择数据源 \xe9\x80\x89\xe6\x8b\xa9\xe6\x95\xb0\xe6\x8d\xae\xe6\xba\x90
|
||||
Sources: 数据源: \xe6\x95\xb0\xe6\x8d\xae\xe6\xba\x90\x3a
|
||||
Select 选择 \xe9\x80\x89\xe6\x8b\xa9
|
||||
Cancel 取消 \xe5\x8f\x96\xe6\xb6\x88
|
||||
|
||||
|
||||
TWLG_CHINESE_HONGKONG, CHINESEBIG5_CHARSET, MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_HONGKONG)
|
||||
TWLG_CHINESE_TAIWAN, CHINESEBIG5_CHARSET, MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_TRADITIONAL)
|
||||
TWLG_CHINESE_TRADITIONAL, CHINESEBIG5_CHARSET, MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_TRADITIONAL)
|
||||
Select Source 選擇影像來源 \xe9\x81\xb8\xe6\x93\x87\xe5\xbd\xb1\xe5\x83\x8f\xe4\xbe\x86\xe6\xba\x90
|
||||
Sources: 影像來源: \xe5\xbd\xb1\xe5\x83\x8f\xe4\xbe\x86\xe6\xba\x90\x3a
|
||||
Select 確定 \xe7\xa2\xba\xe5\xae\x9a
|
||||
Cancel 取消 \xe5\x8f\x96\xe6\xb6\x88
|
||||
|
||||
|
||||
TWLG_CROATIA, EASTEUROPE_CHARSET, MAKELANGID(LANG_CROATIAN,SUBLANG_NEUTRAL)
|
||||
Select Source
|
||||
Sources:
|
||||
Select
|
||||
Cancel Odustani \x4f\x64\x75\x73\x74\x61\x6e\x69
|
||||
|
||||
|
||||
TWLG_CZECH, EASTEUROPE_CHARSET, MAKELANGID(LANG_CZECH,SUBLANG_DEFAULT)
|
||||
Select Source
|
||||
Sources:
|
||||
Select
|
||||
Cancel Storno \x53\x74\x6f\x72\x6e\x6f
|
||||
|
||||
|
||||
TWLG_DANISH, ANSI_CHARSET, MAKELANGID(LANG_DANISH,SUBLANG_NEUTRAL)
|
||||
Select Source: Vælg Enhed \x56\xC3\xA6\x6C\x67\x20\x45\x6E\x68\x65\x64
|
||||
Source: Enhed \x45\x6E\x68\x65\x64
|
||||
Select:Vælg \x56\xE6\x6C\x67
|
||||
Cancel: Annuller \x41\x6E\x6E\x75\x6C\x6C\x65\x72
|
||||
|
||||
TWLG_DOGRI, 0, 0
|
||||
|
||||
|
||||
TWLG_DUTCH, ANSI_CHARSET, MAKELANGID(LANG_DUTCH,SUBLANG_DUTCH)
|
||||
TWLG_DUTCH_BELGIAN, ANSI_CHARSET, MAKELANGID(LANG_DUTCH,SUBLANG_DUTCH_BELGIAN)
|
||||
Select Source Selecteer bron \x53\x65\x6c\x65\x63\x74\x65\x65\x72\x20\x62\x72\x6f\x6e
|
||||
Sources: Bronnen: \x42\x72\x6f\x6e\x6e\x65\x6e\x3a
|
||||
Select Selecteren \x53\x65\x6c\x65\x63\x74\x65\x72\x65\x6e
|
||||
Cancel Annuleren \x41\x6e\x6e\x75\x6c\x65\x72\x65\x6e
|
||||
|
||||
|
||||
TWLG_ENGLISH, ANSI_CHARSET, MAKELANGID(LANG_ENGLISH,SUBLANG_NEUTRAL)
|
||||
TWLG_ENGLISH_AUSTRALIAN, ANSI_CHARSET, MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_AUS)
|
||||
TWLG_ENGLISH_CANADIAN, ANSI_CHARSET, MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_CAN)
|
||||
TWLG_ENGLISH_IRELAND, ANSI_CHARSET, MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_EIRE)
|
||||
TWLG_ENGLISH_NEWZEALAND, ANSI_CHARSET, MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_NZ)
|
||||
TWLG_ENGLISH_SOUTHAFRICA, ANSI_CHARSET, MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_SOUTH_AFRICA)
|
||||
TWLG_ENGLISH_UK, ANSI_CHARSET, MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_UK)
|
||||
TWLG_ENGLISH_USA, ANSI_CHARSET, MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US)
|
||||
Select Source Select Source \x53\x65\x6c\x65\x63\x74\x20\x53\x6f\x75\x72\x63\x65
|
||||
Sources: Sources: \x53\x6f\x75\x72\x63\x65\x73\x3a
|
||||
Select Select \x53\x65\x6c\x65\x63\x74
|
||||
Cancel Cancel \x43\x61\x6e\x63\x65\x6c
|
||||
|
||||
|
||||
TWLG_ESTONIAN, BALTIC_CHARSET, MAKELANGID(LANG_ESTONIAN,SUBLANG_NEUTRAL)
|
||||
Select Source
|
||||
Sources:
|
||||
Select
|
||||
Cancel Kustuta \x4b\x75\x73\x74\x75\x74\x61
|
||||
|
||||
|
||||
TWLG_FAEROESE, EASTEUROPE_CHARSET, MAKELANGID(LANG_FAEROESE,SUBLANG_NEUTRAL)
|
||||
TWLG_FARSI, ARABIC_CHARSET, MAKELANGID(LANG_FARSI,SUBLANG_NEUTRAL)
|
||||
|
||||
|
||||
TWLG_FINNISH, ANSI_CHARSET, MAKELANGID(LANG_FINNISH,SUBLANG_NEUTRAL)
|
||||
Select Source
|
||||
Sources:
|
||||
Select
|
||||
Cancel Peruuta \x50\x65\x72\x75\x75\x74\x61
|
||||
|
||||
|
||||
TWLG_FRENCH, ANSI_CHARSET, MAKELANGID(LANG_FRENCH,SUBLANG_FRENCH)
|
||||
TWLG_FRENCH_BELGIAN, ANSI_CHARSET, MAKELANGID(LANG_FRENCH,SUBLANG_FRENCH_BELGIAN)
|
||||
TWLG_FRENCH_CANADIAN, ANSI_CHARSET, MAKELANGID(LANG_FRENCH,SUBLANG_FRENCH_CANADIAN)
|
||||
TWLG_FRENCH_LUXEMBOURG, ANSI_CHARSET, MAKELANGID(LANG_FRENCH,SUBLANG_FRENCH_LUXEMBOURG)
|
||||
TWLG_FRENCH_SWISS, ANSI_CHARSET, MAKELANGID(LANG_FRENCH,SUBLANG_FRENCH_SWISS)
|
||||
Select Source Sélectionner source \x53\xc3\xa9\x6c\x65\x63\x74\x69\x6f\x6e\x6e\x65\x72\x20\x73\x6f\x75\x72\x63\x65
|
||||
Sources: Sources: \x53\x6f\x75\x72\x63\x65\x73\x3a
|
||||
Select Sélectionner \x53\xc3\xa9\x6c\x65\x63\x74\x69\x6f\x6e\x6e\x65\x72
|
||||
Cancel Annuler \x41\x6e\x6e\x75\x6c\x65\x72
|
||||
|
||||
|
||||
TWLG_GERMAN, ANSI_CHARSET, MAKELANGID(LANG_GERMAN,SUBLANG_GERMAN)
|
||||
TWLG_GERMAN_AUSTRIAN, ANSI_CHARSET, MAKELANGID(LANG_GERMAN,SUBLANG_GERMAN_AUSTRIAN)
|
||||
TWLG_GERMAN_LIECHTENSTEIN, ANSI_CHARSET, MAKELANGID(LANG_GERMAN,SUBLANG_GERMAN_LIECHTENSTEIN)
|
||||
TWLG_GERMAN_LUXEMBOURG, ANSI_CHARSET, MAKELANGID(LANG_GERMAN,SUBLANG_GERMAN_LUXEMBOURG)
|
||||
TWLG_GERMAN_SWISS, ANSI_CHARSET, MAKELANGID(LANG_GERMAN,SUBLANG_GERMAN_SWISS)
|
||||
Select Source Quelle wählen \x51\x75\x65\x6c\x6c\x65\x20\x77\xc3\xa4\x68\x6c\x65\x6e
|
||||
Sources: Quellen: \x51\x75\x65\x6c\x6c\x65\x6e\x3a
|
||||
Select Auswählen \x41\x75\x73\x77\xc3\xa4\x68\x6c\x65\x6e
|
||||
Cancel Abbrechen \x41\x62\x62\x72\x65\x63\x68\x65\x6e
|
||||
|
||||
|
||||
TWLG_GREEK, GREEK_CHARSET, MAKELANGID(LANG_GREEK,SUBLANG_DEFAULT)
|
||||
TWLG_GUJARATI, GREEK_CHARSET, MAKELANGID(LANG_GUJARATI,SUBLANG_DEFAULT)
|
||||
TWLG_HARYANVI, 0, 0
|
||||
TWLG_HEBREW, HEBREW_CHARSET, MAKELANGID(LANG_HEBREW,SUBLANG_NEUTRAL)
|
||||
TWLG_HINDI, HEBREW_CHARSET, MAKELANGID(LANG_HINDI,SUBLANG_NEUTRAL)
|
||||
|
||||
|
||||
TWLG_HUNGARIAN, EASTEUROPE_CHARSET, MAKELANGID(LANG_HUNGARIAN,SUBLANG_NEUTRAL)
|
||||
Select Source
|
||||
Sources:
|
||||
Select
|
||||
Cancel Mégse \x4d\xc3\xa9\x67\x73\x65
|
||||
|
||||
|
||||
TWLG_ICELANDIC, ANSI_CHARSET, MAKELANGID(LANG_ICELANDIC,SUBLANG_NEUTRAL)
|
||||
|
||||
|
||||
TWLG_INDONESIAN, ANSI_CHARSET, MAKELANGID(LANG_INDONESIAN,SUBLANG_NEUTRAL)
|
||||
Select Source Pilith Sumber \x50\x69\x6c\x69\x74\x68\x20\x53\x75\x6d\x62\x65\x72
|
||||
Sources: Sumber: \x53\x75\x6d\x62\x65\x72\x3a
|
||||
Select Pilith \x50\x69\x6c\x69\x74\x68
|
||||
Cancel Batal \x42\x61\x74\x61\x6c
|
||||
|
||||
|
||||
TWLG_ITALIAN, ANSI_CHARSET, MAKELANGID(LANG_ITALIAN,SUBLANG_ITALIAN)
|
||||
TWLG_ITALIAN_SWISS, ANSI_CHARSET, MAKELANGID(LANG_ITALIAN,SUBLANG_ITALIAN_SWISS)
|
||||
Select Source Seleziona origine \x41\x62\x62\x72\x65\x63\x68\x65\x6e
|
||||
Sources: Origini: \x4f\x72\x69\x67\x69\x6e\x69\x3a
|
||||
Select Seleziona \x53\x65\x6c\x65\x7a\x69\x6f\x6e\x61
|
||||
Cancel Annulla \x41\x6e\x6e\x75\x6c\x6c\x61
|
||||
|
||||
|
||||
TWLG_JAPANESE, SHIFTJIS_CHARSET, MAKELANGID(LANG_JAPANESE,SUBLANG_DEFAULT)
|
||||
Select Source 原稿の選択 \xe5\x8e\x9f\xe7\xa8\xbf\xe3\x81\xae\xe9\x81\xb8\xe6\x8a\x9e
|
||||
Sources: 原稿: \xe5\x8e\x9f\xe7\xa8\xbf\x3a
|
||||
Select 選択 \xe9\x81\xb8\xe6\x8a\x9e
|
||||
Cancel キャンセル \xe3\x82\xad\xe3\x83\xa3\xe3\x83\xb3\xe3\x82\xbb\xe3\x83\xab
|
||||
|
||||
|
||||
TWLG_KANNADA, ANSI_CHARSET, MAKELANGID(LANG_KANNADA,SUBLANG_NEUTRAL)
|
||||
TWLG_KASHMIRI, ANSI_CHARSET, MAKELANGID(LANG_KASHMIRI,SUBLANG_NEUTRAL)
|
||||
|
||||
|
||||
TWLG_KOREAN, HANGUL_CHARSET, MAKELANGID(LANG_KOREAN,SUBLANG_KOREAN)
|
||||
TWLG_KOREAN_JOHAB, JOHAB_CHARSET, MAKELANGID(LANG_KOREAN,SUBLANG_KOREAN)
|
||||
Select Source 장치 선택 \xec\x9e\xa5\xec\xb9\x98\x20\xec\x84\xa0\xed\x83\x9d
|
||||
Sources: 장치 \xec\x9e\xa5\xec\xb9\x98
|
||||
Select 선택 \xec\x84\xa0\xed\x83\x9d
|
||||
Cancel 취소 \xec\xb7\xa8\xec\x86\x8c
|
||||
|
||||
|
||||
TWLG_LATVIAN, BALTIC_CHARSET, MAKELANGID(LANG_LATVIAN,SUBLANG_NEUTRAL)
|
||||
TWLG_LITHUANIAN, BALTIC_CHARSET, MAKELANGID(LANG_LITHUANIAN,SUBLANG_NEUTRAL)
|
||||
TWLG_MALAYALAM, BALTIC_CHARSET, MAKELANGID(LANG_MALAYALAM,SUBLANG_NEUTRAL)
|
||||
TWLG_MARATHI, ANSI_CHARSET, MAKELANGID(LANG_MARATHI,SUBLANG_NEUTRAL)
|
||||
TWLG_MARWARI, 0, 0
|
||||
TWLG_MEGHALAYAN, 0, 0
|
||||
TWLG_MIZO, 0, 0
|
||||
TWLG_NAGA, 0, 0
|
||||
TWLG_NORWEGIAN, ANSI_CHARSET, MAKELANGID(LANG_NORWEGIAN,SUBLANG_NEUTRAL)
|
||||
TWLG_NORWEGIAN_BOKMAL, ANSI_CHARSET, MAKELANGID(LANG_NORWEGIAN,SUBLANG_NORWEGIAN_BOKMAL)
|
||||
TWLG_NORWEGIAN_NYNORSK, ANSI_CHARSET, MAKELANGID(LANG_NORWEGIAN,SUBLANG_NORWEGIAN_NYNORSK)
|
||||
TWLG_ORISSI, 0, 0
|
||||
|
||||
|
||||
TWLG_POLISH, EASTEUROPE_CHARSET, MAKELANGID(LANG_POLISH,SUBLANG_NEUTRAL)
|
||||
Select Source
|
||||
Sources:
|
||||
Select
|
||||
Cancel Anuluj \x41\x6e\x75\x6c\x75\x6a
|
||||
|
||||
|
||||
TWLG_PORTUGUESE, EASTEUROPE_CHARSET, MAKELANGID(LANG_PORTUGUESE,SUBLANG_PORTUGUESE)
|
||||
TWLG_PORTUGUESE_BRAZIL, ANSI_CHARSET, MAKELANGID(LANG_PORTUGUESE,SUBLANG_PORTUGUESE_BRAZILIAN)
|
||||
Select Source Selecionar Origem \x53\x65\x6c\x65\x63\x69\x6f\x6e\x61\x72\x20\x4f\x72\x69\x67\x65\x6d
|
||||
Sources: Origens: \x4f\x72\x69\x67\x65\x6e\x73\x3a
|
||||
Select Selecionar \x53\x65\x6c\x65\x63\x69\x6f\x6e\x61\x72
|
||||
Cancel Cancelar \x43\x61\x6e\x63\x65\x6c\x61\x72
|
||||
|
||||
|
||||
TWLG_PUNJABI, ANSI_CHARSET, MAKELANGID(LANG_PUNJABI,SUBLANG_NEUTRAL)
|
||||
TWLG_PUSHTU, 0, 0
|
||||
TWLG_ROMANIAN, EASTEUROPE_CHARSET, MAKELANGID(LANG_ROMANIAN,SUBLANG_NEUTRAL)
|
||||
|
||||
|
||||
TWLG_RUSSIAN, RUSSIAN_CHARSET, MAKELANGID(LANG_RUSSIAN,SUBLANG_DEFAULT)
|
||||
Select Source Выбрать источник \xd0\x92\xd1\x8b\xd0\xb1\xd1\x80\xd0\xb0\xd1\x82\xd1\x8c\x20\xd0\xb8\xd1\x81\xd1\x82\xd0\xbe\xd1\x87\xd0\xbd\xd0\xb8\xd0\xba
|
||||
Sources: Источники: \xd0\x98\xd1\x81\xd1\x82\xd0\xbe\xd1\x87\xd0\xbd\xd0\xb8\xd0\xba\xd0\xb8\x3a
|
||||
Select Выбрать \xd0\x92\xd1\x8b\xd0\xb1\xd1\x80\xd0\xb0\xd1\x82\xd1\x8c
|
||||
Cancel Отменить \xd0\x9e\xd1\x82\xd0\xbc\xd0\xb5\xd0\xbd\xd0\xb8\xd1\x82\xd1\x8c
|
||||
|
||||
|
||||
TWLG_SERBIAN_CYRILLIC, ANSI_CHARSET, MAKELANGID(LANG_SERBIAN,SUBLANG_SERBIAN_CYRILLIC)
|
||||
TWLG_SERBIAN_LATIN, EASTEUROPE_CHARSET, MAKELANGID(LANG_SERBIAN,SUBLANG_SERBIAN_LATIN)
|
||||
TWLG_SIKKIMI, 0, 0
|
||||
TWLG_SLOVAK, EASTEUROPE_CHARSET, MAKELANGID(LANG_SLOVAK,SUBLANG_NEUTRAL)
|
||||
|
||||
|
||||
TWLG_SLOVENIAN, EASTEUROPE_CHARSET, MAKELANGID(LANG_SLOVENIAN,SUBLANG_NEUTRAL)
|
||||
Select Source
|
||||
Sources:
|
||||
Select
|
||||
Cancel Prekini \x50\x72\x65\x6b\x69\x6e\x69
|
||||
|
||||
|
||||
TWLG_SPANISH, ANSI_CHARSET, MAKELANGID(LANG_SPANISH,SUBLANG_SPANISH)
|
||||
TWLG_SPANISH_MEXICAN, ANSI_CHARSET, MAKELANGID(LANG_SPANISH,SUBLANG_SPANISH_MEXICAN)
|
||||
TWLG_SPANISH_MODERN, ANSI_CHARSET, MAKELANGID(LANG_SPANISH,SUBLANG_SPANISH_MODERN)
|
||||
Select Source Selección de fuente \x53\x65\x6c\x65\x63\x63\x69\xc3\xb3\x6e\x20\x64\x65\x20\x66\x75\x65\x6e\x74\x65
|
||||
Sources: Fuentes: \x46\x75\x65\x6e\x74\x65\x73\x3a
|
||||
Select Seleccionar \x53\x65\x6c\x65\x63\x63\x69\x6f\x6e\x61\x72
|
||||
Cancel Cancelar \x43\x61\x6e\x63\x65\x6c\x61\x72
|
||||
|
||||
|
||||
TWLG_SWEDISH, ANSI_CHARSET, MAKELANGID(LANG_SWEDISH,SUBLANG_SWEDISH)
|
||||
TWLG_SWEDISH_FINLAND, ANSI_CHARSET, MAKELANGID(LANG_SWEDISH,SUBLANG_SWEDISH_FINLAND)
|
||||
Select Source
|
||||
Sources:
|
||||
Select
|
||||
Cancel Avbryt \x41\x76\x62\x72\x79\x74
|
||||
|
||||
|
||||
TWLG_TAMIL, ANSI_CHARSET, MAKELANGID(LANG_TAMIL,SUBLANG_NEUTRAL)
|
||||
TWLG_TELUGU, ANSI_CHARSET, MAKELANGID(LANG_TELUGU,SUBLANG_NEUTRAL)
|
||||
TWLG_THAI, THAI_CHARSET, MAKELANGID(LANG_THAI,SUBLANG_NEUTRAL)
|
||||
TWLG_TRIPURI, 0, 0
|
||||
|
||||
|
||||
TWLG_TURKISH, TURKISH_CHARSET, MAKELANGID(LANG_TURKISH,SUBLANG_DEFAULT)
|
||||
Select Source Kaynak seçiniz \x4b\x61\x79\x6e\x61\x6b\x20\x73\x65\xc3\xa7\x69\x6e\x69\x7a
|
||||
Sources: Kaynak \x4b\x61\x79\x6e\x61\x6b
|
||||
Select Seçiniz \x53\x65\xc3\xa7\x69\x6e\x69\x7a
|
||||
Cancel İptal \xc4\xb0\x70\x74\x61\x6c
|
||||
|
||||
|
||||
TWLG_UKRANIAN, RUSSIAN_CHARSET, MAKELANGID(LANG_UKRAINIAN,SUBLANG_NEUTRAL)
|
||||
TWLG_URDU, ANSI_CHARSET, MAKELANGID(LANG_URDU,SUBLANG_NEUTRAL)
|
||||
TWLG_VIETNAMESE, VIETNAMESE_CHARSET, MAKELANGID(LANG_VIETNAMESE,SUBLANG_NEUTRAL)
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,37 @@
|
|||
# Main and minor version definition
|
||||
# usage: ./build.sh os cpu ---> ./build.sh uos x86_64
|
||||
|
||||
@echo off
|
||||
# clear
|
||||
|
||||
if [ -f ../../build/twaindsm/Makefile ]; then
|
||||
echo ""
|
||||
else
|
||||
mkdir ../../../build
|
||||
mkdir ../../../build/twaindsm
|
||||
fi
|
||||
|
||||
origin_dir=$(pwd)
|
||||
|
||||
cd ../../../build/twaindsm
|
||||
echo building path is $(pwd)
|
||||
rm -rf ./*
|
||||
cmake $origin_dir
|
||||
make -j4
|
||||
|
||||
if [ $? -ne 0 ];then
|
||||
|
||||
err=1
|
||||
echo "--------------------------------------make fail---------------------------------------"
|
||||
# commented, we should restore the CMakeLists.txts...
|
||||
else
|
||||
err=0
|
||||
echo "--------------------------------------make succeed------------------------------------"
|
||||
cp ./libtwaindsm.so.2.5.0 ../../release/$1/$2/libtwaindsm.so
|
||||
fi
|
||||
|
||||
cd $origin_dir
|
||||
|
||||
exit $err
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,5 @@
|
|||
LIBRARY "TWAINDSM"
|
||||
|
||||
EXPORTS
|
||||
DSM_Entry
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,139 @@
|
|||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#define APSTUDIO_HIDDEN_SYMBOLS
|
||||
#include "windows.h"
|
||||
#undef APSTUDIO_HIDDEN_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
|
||||
"#include ""windows.h""\r\n"
|
||||
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION TWNDSM_VERSION_NUM
|
||||
PRODUCTVERSION TWNDSM_VERSION_NUM
|
||||
FILEFLAGSMASK 0x1fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x9L
|
||||
#else
|
||||
FILEFLAGS 0x8L
|
||||
#endif
|
||||
FILEOS 0x4L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", TWNDSM_ORGANIZATION
|
||||
VALUE "FileDescription", TWNDSM_DESCRIPTION
|
||||
VALUE "FileVersion", TWNDSM_VERSION_STR
|
||||
VALUE "InternalName", "DSM"
|
||||
VALUE "LegalCopyright", "(C) 1993-2021 TWAIN Working Group. All rights reserved."
|
||||
VALUE "OriginalFilename", "TWAIN_32.dll"
|
||||
VALUE "ProductName", "TWAIN DSM Dynamic Link Library"
|
||||
VALUE "ProductVersion", TWNDSM_VERSION_STR
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
|
||||
IDD_DLG_SOURCE DIALOGEX 64, 60, 245, 89
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Select Source"
|
||||
FONT 8, "Arial Unicode MS", 400, 0, 0x0
|
||||
BEGIN
|
||||
PUSHBUTTON "Select",IDOK,177,43,62,15,WS_GROUP
|
||||
PUSHBUTTON "Cancel",IDCANCEL,177,63,62,15
|
||||
LTEXT "Sources:",IDC_STATIC,9,6,85,8,NOT WS_GROUP
|
||||
LISTBOX ID_LST_SOURCES,8,16,164,71,LBS_SORT | WS_VSCROLL | WS_GROUP | WS_TABSTOP
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DESIGNINFO
|
||||
//
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
GUIDELINES DESIGNINFO
|
||||
BEGIN
|
||||
IDD_DLG_SOURCE, DIALOG
|
||||
BEGIN
|
||||
RIGHTMARGIN, 244
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
|
@ -0,0 +1,854 @@
|
|||
/*
|
||||
* [Overview]
|
||||
* The contents of this module allow the new TWAINDSM.DLL (tied to the 2.x version
|
||||
* of the TWAIN Specifiction) to hook functions that might try to access the 1.x
|
||||
* TWAIN_32.DLL. We need this because the DG_CONTROL/DAT_NULL/MSG_* triplets are
|
||||
* sent from the data source (driver) to the application through the data source
|
||||
* manager (DSM). The technique used was for a driver to issue a LoadLibrary or
|
||||
* a GetModuleHandle, which would result in it attaching to the same TWAIN_32.DLL
|
||||
* first loaded by the application. We have to force the driver to attach to the
|
||||
* new TWAINDSM.DLL instead.
|
||||
*
|
||||
*
|
||||
* [Diagram]
|
||||
* This is the problem we have...
|
||||
* +-----+ +--------------+ +--------------+
|
||||
* | app | <-------> | TWAINDSM.DLL | --------> | |
|
||||
* +-----+ +--------------+ | |
|
||||
* | driver (1.x) |
|
||||
* +--------------+ | |
|
||||
* error <----- | TWAIN_32.DLL | <-------- | |
|
||||
* +--------------+ +--------------+
|
||||
*
|
||||
* By hooking the appropriate function, we change the driver's request to get
|
||||
* the DSM_Entry function from TWAIN_32.DLL into the DSM_Entry function from
|
||||
* DSM_ TWAINDSM.DLL
|
||||
* +-----+ +--------------+ +--------------+
|
||||
* | app | <-------> | TWAINDSM.DLL | <-------> | |
|
||||
* +-----+ +--------------+ | |
|
||||
* | driver (1.x) |
|
||||
* +--------------+ | |
|
||||
* | TWAIN_32.DLL | | |
|
||||
* +--------------+ +--------------+
|
||||
*
|
||||
* Note that TWAIN_32.DLL is still in the picture. This is intentional,
|
||||
* because we're (indirectly) hooking GetProcAddress. The driver still
|
||||
* does a LoadLibrary or GetModuleHandle on TWAIN_32.DLL. This design
|
||||
* was selected because it results in the smallest possible hook code,
|
||||
* and makes the smallest possible change to the 1.x driver. Everything
|
||||
* runs the same as a TWAIN_32.DLL session, we just return a pointer to
|
||||
* a different DSM_Entry function.
|
||||
*
|
||||
*
|
||||
* [Hooked Functions]
|
||||
* This is the ntdll.dll function we're hooking from kernel32.dll...
|
||||
* LdrGetProcedureAddress (or LdrGetProcedureAddressForCaller)
|
||||
* This gives us full coverage for the following function...
|
||||
* GetProcAddress
|
||||
*
|
||||
*
|
||||
* [Solution]
|
||||
* The hook code is derived from the BugSlayer HookImportedFunctionByName function
|
||||
* described in the August 1998 MSJ. The code has been considerably simplified to
|
||||
* meet the limited needs of the DSM.
|
||||
*
|
||||
*
|
||||
* [Risks]
|
||||
* 32-bit Windows applications using TWAINDSM.DLL will never be able to access
|
||||
* the TWAIN_32.DLL DSM_Entry function. Since this is by design, it's not so
|
||||
* much a risk as "the plan", but it still deserves to be mentioned.
|
||||
*
|
||||
* We're not fully loading the TWAIN_32.DLL, because we don't have control over
|
||||
* it, and we can't be sure what it's doing in DllMain. This could be a problem
|
||||
* with a very badly behaved application. The scenerio is so convoluted, though,
|
||||
* that it seems a good risk to keep TWAIN_32.DLL as uninvolved as possible.
|
||||
*
|
||||
* The application will crash if it does a FreeLibrary() on the DSM without first
|
||||
* doing all the necessary MSG_CLOSEDS and MSG_CLOSEDSM calls. This can be
|
||||
* mitigated by hooking LdrUnloadDll() and watching for an attempt to unload the
|
||||
* DSM. But this adds complexity that rewards extremely bad coding behavior, so
|
||||
* it's not going to be added unless we have a lot of bad actors we have to deal
|
||||
* with.
|
||||
*
|
||||
* Hooks should be avoided whenever possible. Therefore the DSM code only installs
|
||||
* the hook if the application attempts to DG_CONTROL/DAT_IDENTITY/MSG_OPENDS a 1.x
|
||||
* driver on a 32-bit Windows system.
|
||||
*
|
||||
* This system is only designed to work with Window 2000 and higher, there is no
|
||||
* intention of supporting either Windows NT or any of the Windows 9x platforms.
|
||||
* Nor is there a reason to, since they don't have a file protection scheme (save for
|
||||
* WinME, but hopefully nobody is still using that)...
|
||||
*/
|
||||
|
||||
#include "dsm.h"
|
||||
|
||||
|
||||
/**
|
||||
* This entire file is only used for 32-bit Windows systems, so there is no need to
|
||||
* compile it for anything else...
|
||||
*/
|
||||
#if TWNDSM_OS_64BIT
|
||||
#pragma message( "hook code disabled for 64-bit builds..." )
|
||||
#elif TWNDSM_OS_32BIT
|
||||
#pragma message( "hook code enabled for 32-bit builds..." )
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* We use this to build pointers from the various data structures we
|
||||
* have to navigate to set up the hooks...
|
||||
*/
|
||||
#define MakePtr(cast,ptr,AddValue) (cast)((DWORD_PTR)(ptr)+(DWORD_PTR)(AddValue))
|
||||
|
||||
|
||||
/**
|
||||
* Things we do with our Hook function...
|
||||
*/
|
||||
enum EHOOK
|
||||
{
|
||||
HOOK_ATTACH = 0,
|
||||
HOOK_DETACH = 1
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Need this for our Ldr functions...
|
||||
*/
|
||||
typedef struct _ANSI_STRING {
|
||||
USHORT Length;
|
||||
USHORT MaximumLength;
|
||||
PSTR Buffer;
|
||||
} ANSI_STRING, *PANSI_STRING;
|
||||
|
||||
|
||||
/**
|
||||
* typedefs of our hooked functions, so we can cast them nice when we make
|
||||
* our calls...
|
||||
*/
|
||||
typedef NTSYSAPI DWORD (NTAPI *LdrGetProcedureAddress_t)
|
||||
(
|
||||
__in HMODULE ModuleHandle,
|
||||
__in_opt PANSI_STRING FunctionName,
|
||||
__in_opt WORD Oridinal,
|
||||
__out PVOID *FunctionAddress
|
||||
);
|
||||
typedef NTSYSAPI DWORD (NTAPI *LdrGetProcedureAddressForCaller_t)
|
||||
(
|
||||
__in HMODULE ModuleHandle,
|
||||
__in_opt PANSI_STRING FunctionName,
|
||||
__in_opt WORD Oridinal,
|
||||
__out PVOID *FunctionAddress,
|
||||
__in BOOL bValue,
|
||||
__in PVOID *CallbackAddress
|
||||
);
|
||||
|
||||
/**
|
||||
* Forward declarations for our functions, so we can build our m_proc table...
|
||||
*/
|
||||
DWORD NTAPI LocalLdrGetProcedureAddress
|
||||
(
|
||||
__in HMODULE ModuleHandle,
|
||||
__in_opt PANSI_STRING FunctionName,
|
||||
__in_opt WORD Oridinal,
|
||||
__out PVOID *FunctionAddress
|
||||
);
|
||||
DWORD NTAPI LocalLdrGetProcedureAddressForCaller
|
||||
(
|
||||
__in HMODULE ModuleHandle,
|
||||
__in_opt PANSI_STRING FunctionName,
|
||||
__in_opt WORD Oridinal,
|
||||
__out PVOID *FunctionAddress,
|
||||
__in BOOL bValue,
|
||||
__in PVOID *CallbackAddress
|
||||
);
|
||||
|
||||
/**
|
||||
* The entry point we want to return to the caller, instead of the one they
|
||||
* thought they were getting from TWAIN_32.DLL...
|
||||
*/
|
||||
extern DSMENTRY DSM_Entry
|
||||
(
|
||||
TW_IDENTITY *_pOrigin,
|
||||
TW_IDENTITY *_pDest,
|
||||
TW_UINT32 _DG,
|
||||
TW_UINT16 _DAT,
|
||||
TW_UINT16 _MSG,
|
||||
TW_MEMREF _pData
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* The hook class...
|
||||
*/
|
||||
class CTwHook
|
||||
{
|
||||
public:
|
||||
|
||||
// Initialize our piece-of-data...
|
||||
CTwHook()
|
||||
{
|
||||
memset(&pod,0,sizeof(pod));
|
||||
}
|
||||
|
||||
// The destructor cleans us all up (but Hook does the real work)...
|
||||
~CTwHook()
|
||||
{
|
||||
Hook(HOOK_DETACH);
|
||||
memset(&pod,0,sizeof(pod));
|
||||
}
|
||||
|
||||
// The workhorse, this is where the hooking fun really takes place...
|
||||
bool Hook
|
||||
(
|
||||
EHOOK _ehook
|
||||
);
|
||||
|
||||
// Determine if this DS ID has been hooked
|
||||
bool DSID_Is_Hooked
|
||||
(
|
||||
TW_UINT32 DSID
|
||||
);
|
||||
|
||||
// Add this DS ID as being hooked
|
||||
void Hook_Add_DSID
|
||||
(
|
||||
TW_UINT32 DSID
|
||||
);
|
||||
|
||||
// Remove this DS ID as being hooked
|
||||
bool Hook_Remove_DSID
|
||||
(
|
||||
TW_UINT32 DSID
|
||||
);
|
||||
|
||||
private:
|
||||
|
||||
// We use a pod so that we don't have to worry about initialization
|
||||
// issues...
|
||||
struct Pod
|
||||
{
|
||||
PROC pOriginal; // The original procedure we found
|
||||
TW_UINT32 HookedDSs[MAX_NUM_DS];
|
||||
} pod;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This is where we're keeping our stuff, it has global scope in this module so we can
|
||||
* use it in our hook functions. Even though this is static, every attempt has been
|
||||
* made to make it thread safe. We also have a reference counter, since the application
|
||||
* may choose to load more than one 1.x driver...
|
||||
*/
|
||||
static int s_iHookCount = 0;
|
||||
static CTwHook *s_ptwhook = (CTwHook*)NULL;
|
||||
|
||||
|
||||
/**
|
||||
* We start by loading these functions using GetProcAddress, since they are
|
||||
* wacky NTDLL things that are undocumented. Later on we change them to the
|
||||
* actual pointers to the Ldr functions, and this is what allows us to be
|
||||
* used safely, no matter what the state of the CTwHook object is in...
|
||||
*/
|
||||
static LdrGetProcedureAddress_t OriginalLdrGetProcedureAddress = 0;
|
||||
static LdrGetProcedureAddressForCaller_t OriginalLdrGetProcedureAddressForCaller = 0;
|
||||
|
||||
|
||||
/**
|
||||
* A static value for the TWAIN_32.DLL we load, which provides us a very
|
||||
* simple way to see if someone is working with this DLL...
|
||||
*/
|
||||
static HMODULE s_hmoduleTWAIN32 = 0;
|
||||
|
||||
/**
|
||||
* A static value for the DSMEntry of the TWAIN_32.DLL we load,
|
||||
* which provides us a way to call the original TWAIN_32 if we
|
||||
* did not want to hook this data souce.
|
||||
*/
|
||||
static DSMENTRYPROC TWAIN32_DSMEntry = 0;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The entry point we want to return to the caller, instead of the one they
|
||||
* thought they were getting from TWAIN_32.DLL...
|
||||
*/
|
||||
DSMENTRY DSM_HookedEntry
|
||||
(
|
||||
TW_IDENTITY *_pOrigin,
|
||||
TW_IDENTITY *_pDest,
|
||||
TW_UINT32 _DG,
|
||||
TW_UINT16 _DAT,
|
||||
TW_UINT16 _MSG,
|
||||
TW_MEMREF _pData
|
||||
)
|
||||
{
|
||||
if ( ((_DAT == DAT_NULL)
|
||||
|| (_DAT == DAT_CALLBACK && _MSG == MSG_INVOKE_CALLBACK))
|
||||
&& _pOrigin
|
||||
&& s_ptwhook
|
||||
&& s_ptwhook->DSID_Is_Hooked(_pOrigin->Id))
|
||||
{
|
||||
return (DSM_Entry(_pOrigin,_pDest,_DG,_DAT,_MSG,_pData));
|
||||
}
|
||||
|
||||
return (TWAIN32_DSMEntry(_pOrigin,_pDest,_DG,_DAT,_MSG,_pData));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Derived from John Robbins' BugSlayer code in MSJ (so the 'I' in the comments in this
|
||||
* function refers to John), this function hooks or unhooks the stuff we want to examine.
|
||||
* Note that this code is optimized to hook the Ldr functions in ntdll.dll. If you want
|
||||
* to hook something else, especially if it's in a different DLL, you're going to have
|
||||
* some work to do...
|
||||
* @param[in] EHOOK _ehook we're hooking or unhooking
|
||||
* @return true or false
|
||||
*/
|
||||
bool CTwHook::Hook
|
||||
(
|
||||
EHOOK _ehook
|
||||
)
|
||||
{
|
||||
UINT uResult;
|
||||
BOOL boolResult;
|
||||
PIMAGE_IMPORT_DESCRIPTOR pImportDesc;
|
||||
PIMAGE_THUNK_DATA pOrigThunk;
|
||||
PIMAGE_THUNK_DATA pRealThunk;
|
||||
PIMAGE_IMPORT_BY_NAME pByName;
|
||||
bool bDoHook;
|
||||
MEMORY_BASIC_INFORMATION mbi_thunk;
|
||||
DWORD_PTR *pTemp;
|
||||
DWORD dwOldProtect;
|
||||
PIMAGE_DOS_HEADER pDOSHeader;
|
||||
PIMAGE_NT_HEADERS pNTHeader;
|
||||
PSTR szCurrMod;
|
||||
HMODULE hmodule;
|
||||
char szTwain32[MAX_PATH];
|
||||
const char *szFunctionName;
|
||||
|
||||
// Initialize stuff when we're doing an attach...
|
||||
if (_ehook == HOOK_ATTACH)
|
||||
{
|
||||
// If we don't find TWAIN_32.DLL, then we're not going to
|
||||
// make life any better by doing the hooks, so bail. Also,
|
||||
// We're not going to allow any flavor of GetProcAddress
|
||||
// to access this library, which is why we're using the
|
||||
// extra flag, to keep TWAIN_32.DLL from loading anything
|
||||
// other than itself.
|
||||
//
|
||||
// BUG ALERT
|
||||
// ~~~~~~~~~
|
||||
// There is a potential bug here, but one that depends
|
||||
// on really bad behavior. If the application loads
|
||||
// TWAINDSM.DLL, then loads TWAIN_32.DLL, then unloads
|
||||
// TWAINDSM.DLL, then does a GetProcAddress for DSM_Entry
|
||||
// with TWAIN_32.DLL, it's going to go ka-boom. If this
|
||||
// is a problem, then go back to using ::LoadLibrary()...
|
||||
memset(szTwain32,0,sizeof(szTwain32));
|
||||
uResult = ::GetWindowsDirectory(szTwain32,sizeof(szTwain32)-1);
|
||||
if (!uResult)
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
SSTRCAT(szTwain32,sizeof(szTwain32)-1,"\\TWAIN_32.DLL");
|
||||
s_hmoduleTWAIN32 = ::LoadLibraryEx(szTwain32,NULL,DONT_RESOLVE_DLL_REFERENCES);
|
||||
if (0 == s_hmoduleTWAIN32)
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
|
||||
// Load the undocumented routine, we're going for both, if we find
|
||||
// LdrGetProcedureAddressForCaller, then we'll prefer it over LdrGetProcedureAddress...
|
||||
szFunctionName = "";
|
||||
OriginalLdrGetProcedureAddress = 0;
|
||||
OriginalLdrGetProcedureAddressForCaller = 0;
|
||||
hmodule = GetModuleHandle("ntdll.dll");
|
||||
if (hmodule)
|
||||
{
|
||||
szFunctionName = "LdrGetProcedureAddressForCaller";
|
||||
OriginalLdrGetProcedureAddressForCaller = (LdrGetProcedureAddressForCaller_t)GetProcAddress(hmodule,szFunctionName);
|
||||
if (!OriginalLdrGetProcedureAddressForCaller)
|
||||
{
|
||||
szFunctionName = "LdrGetProcedureAddress";
|
||||
OriginalLdrGetProcedureAddress = (LdrGetProcedureAddress_t)GetProcAddress(hmodule,szFunctionName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we're detaching, then make sure our reference to TWAIN_32.DLL is gone...
|
||||
else
|
||||
{
|
||||
if (s_hmoduleTWAIN32)
|
||||
{
|
||||
::FreeLibrary(s_hmoduleTWAIN32);
|
||||
s_hmoduleTWAIN32 = 0;
|
||||
}
|
||||
|
||||
// If we don't have an old pointer, then we're done...
|
||||
if (NULL == pod.pOriginal)
|
||||
{
|
||||
return (true);
|
||||
}
|
||||
|
||||
// Pick the name...
|
||||
if (OriginalLdrGetProcedureAddressForCaller)
|
||||
{
|
||||
szFunctionName = "LdrGetProcedureAddressForCaller";
|
||||
}
|
||||
else
|
||||
{
|
||||
szFunctionName = "LdrGetProcedureAddress";
|
||||
}
|
||||
}
|
||||
|
||||
// This is where we'll be hooking into Ldr functions, the calls
|
||||
// themselves are in ntdll.dll. Kernel32 calls them, and that's
|
||||
// where we can take advantage of the DLL indirection to do this
|
||||
// spiffy DLL injection thingy...
|
||||
// Starting with Windows7 the hooking has moved from kernel32.dll
|
||||
// to a new library kernelbase.dll. Atempt kernelbase first
|
||||
// if it fails then we are not Windows7 and try kernel32
|
||||
hmodule = GetModuleHandle("kernelbase.dll");
|
||||
if ( NULL == hmodule )
|
||||
{
|
||||
hmodule = GetModuleHandle("kernel32.dll");
|
||||
}
|
||||
|
||||
// Get the DOS header...
|
||||
pDOSHeader = (PIMAGE_DOS_HEADER)hmodule;
|
||||
|
||||
// Is this the MZ header?
|
||||
if ( !pDOSHeader
|
||||
|| (TRUE == IsBadReadPtr(pDOSHeader,sizeof(IMAGE_DOS_HEADER)))
|
||||
|| (IMAGE_DOS_SIGNATURE != pDOSHeader->e_magic))
|
||||
{
|
||||
return (false);
|
||||
}
|
||||
|
||||
// Get the PE header.
|
||||
pNTHeader = MakePtr(PIMAGE_NT_HEADERS,pDOSHeader,pDOSHeader->e_lfanew);
|
||||
|
||||
// Is this a real PE image?
|
||||
if ( (TRUE == IsBadReadPtr(pNTHeader,sizeof(IMAGE_NT_HEADERS)))
|
||||
|| (IMAGE_NT_SIGNATURE != pNTHeader->Signature))
|
||||
{
|
||||
return (false);
|
||||
}
|
||||
|
||||
// If there is no imports section, leave now.
|
||||
if (0 == pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
|
||||
{
|
||||
return (false);
|
||||
}
|
||||
|
||||
// Get the pointer to the imports section.
|
||||
pImportDesc = MakePtr(PIMAGE_IMPORT_DESCRIPTOR,pDOSHeader,pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
|
||||
|
||||
// Loop through the import module descriptors looking for the
|
||||
// ntdll.dll module, which is where the Ldr functions live...
|
||||
while (NULL != pImportDesc->Name)
|
||||
{
|
||||
szCurrMod = MakePtr(PSTR,pDOSHeader,pImportDesc->Name);
|
||||
if (0 == _stricmp(szCurrMod,"ntdll.dll"))
|
||||
{
|
||||
// Found it.
|
||||
break;
|
||||
}
|
||||
// Look at the next one.
|
||||
pImportDesc++ ;
|
||||
}
|
||||
|
||||
// If the name is NULL, then the module is not imported.
|
||||
if (NULL == pImportDesc->Name)
|
||||
{
|
||||
return (false);
|
||||
}
|
||||
|
||||
// Get the original thunk information for this DLL. I can't use
|
||||
// the thunk information stored in pImportDesc->FirstThunk
|
||||
// because the loader has already changed that array to fix up
|
||||
// all the imports. The original thunk gives me access to the
|
||||
// function names.
|
||||
pOrigThunk = MakePtr(PIMAGE_THUNK_DATA,hmodule,pImportDesc->OriginalFirstThunk);
|
||||
|
||||
// Get the array the pImportDesc->FirstThunk points to because
|
||||
// I'll do the actual bashing and hooking there.
|
||||
pRealThunk = MakePtr(PIMAGE_THUNK_DATA,hmodule,pImportDesc->FirstThunk);
|
||||
|
||||
// Determines whether I hook the function
|
||||
bDoHook = false;
|
||||
|
||||
// Loop through and find the function to hook.
|
||||
while (NULL != pOrigThunk->u1.Function)
|
||||
{
|
||||
// Look only at functions that are imported by name, not those
|
||||
// that are imported by ordinal value.
|
||||
if (IMAGE_ORDINAL_FLAG != (pOrigThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG))
|
||||
{
|
||||
// Look at the name of this imported function.
|
||||
pByName = MakePtr(PIMAGE_IMPORT_BY_NAME,hmodule,pOrigThunk->u1.AddressOfData);
|
||||
|
||||
// We found it, so scoot...
|
||||
if ( pByName->Name
|
||||
&& ('\0' != pByName->Name[0])
|
||||
&& (0 == _stricmp(szFunctionName,(char*)pByName->Name)))
|
||||
{
|
||||
bDoHook = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Increment both tables, and continue...
|
||||
pOrigThunk++;
|
||||
pRealThunk++;
|
||||
}
|
||||
}
|
||||
|
||||
// If we found something, then hook or unhook it, as appropriate...
|
||||
if (true == bDoHook)
|
||||
{
|
||||
// I found a function to hook. Now I need to change
|
||||
// the memory protection to writable before I overwrite
|
||||
// the function pointer. Note that I'm now writing into
|
||||
// the real thunk area!
|
||||
VirtualQuery(pRealThunk,&mbi_thunk,sizeof(MEMORY_BASIC_INFORMATION));
|
||||
if (FALSE == VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize,PAGE_EXECUTE_READWRITE,&mbi_thunk.Protect))
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
|
||||
// Save the original address, if we're hooking...
|
||||
if (_ehook == HOOK_ATTACH)
|
||||
{
|
||||
// This cast should make the compiler happy about the change in the word size...
|
||||
pod.pOriginal = (PROC)(INT_PTR)pRealThunk->u1.Function;
|
||||
if (OriginalLdrGetProcedureAddressForCaller)
|
||||
{
|
||||
OriginalLdrGetProcedureAddressForCaller = (LdrGetProcedureAddressForCaller_t)pod.pOriginal;
|
||||
}
|
||||
else
|
||||
{
|
||||
OriginalLdrGetProcedureAddress = (LdrGetProcedureAddress_t)pod.pOriginal;
|
||||
}
|
||||
}
|
||||
|
||||
// Microsoft has two different definitions of the
|
||||
// PIMAGE_THUNK_DATA fields as they are moving to
|
||||
// support Win64. The W2K RC2 Platform SDK is the
|
||||
// latest header, so I'll use that one and force the
|
||||
// Visual C++ 6 Service Pack 3 headers to deal with it.
|
||||
|
||||
// Hook the new function if we're hooking, or the original function
|
||||
// if we're closing...
|
||||
if (_ehook == HOOK_ATTACH)
|
||||
{
|
||||
pTemp = (DWORD_PTR*)&pRealThunk->u1.Function;
|
||||
if (OriginalLdrGetProcedureAddressForCaller)
|
||||
{
|
||||
*pTemp = (DWORD_PTR)LocalLdrGetProcedureAddressForCaller;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pTemp = (DWORD_PTR)LocalLdrGetProcedureAddress;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pTemp = (DWORD_PTR*)&pRealThunk->u1.Function;
|
||||
*pTemp = (DWORD_PTR)(pod.pOriginal);
|
||||
}
|
||||
|
||||
// Change the protection back to what it was before I
|
||||
// overwrote the function pointer.
|
||||
boolResult = VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize,mbi_thunk.Protect,&dwOldProtect);
|
||||
if (boolResult == FALSE)
|
||||
{
|
||||
// Okay, this isn't good, but we're not going to do
|
||||
// anything about it, because presumably this isn't
|
||||
// the end of the world...
|
||||
}
|
||||
}
|
||||
|
||||
// All done...
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the DS has been hooked by checking the ID
|
||||
* @param[in] DSID The DS ID to check to see if it has been hooked
|
||||
* @return true or false
|
||||
*/
|
||||
bool CTwHook::DSID_Is_Hooked(TW_UINT32 DSID)
|
||||
{
|
||||
int count = min(MAX_NUM_DS,s_iHookCount);
|
||||
for (int i=0; i<count; i++)
|
||||
{
|
||||
if (pod.HookedDSs[i] == DSID)
|
||||
{
|
||||
return (true);
|
||||
}
|
||||
}
|
||||
return (false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add this DS to the list of being hooked
|
||||
* @param[in] DSID The DS ID to add to the list
|
||||
* @note We allow an application to open the DSM several times and each
|
||||
* application to open several DSs. (The application must use a different
|
||||
* name each time it loads the DSM). It is possible for a DS to be opened
|
||||
* several times by different applications. (Although most DSs only support
|
||||
* one connection.) Therefore we need to allow multiple instances of the
|
||||
* same DSID. No duplicate check needed.
|
||||
*/
|
||||
void CTwHook::Hook_Add_DSID(TW_UINT32 DSID)
|
||||
{
|
||||
pod.HookedDSs[s_iHookCount] = DSID;
|
||||
s_iHookCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove this DS from the list of being hooked
|
||||
* @param[in] DSID The DS ID to remove from the list
|
||||
* @return true or false
|
||||
*/
|
||||
bool CTwHook::Hook_Remove_DSID(TW_UINT32 DSID)
|
||||
{
|
||||
int count = min(MAX_NUM_DS, s_iHookCount);
|
||||
|
||||
for(int i=0; i<count; i++)
|
||||
{
|
||||
if(pod.HookedDSs[i] == DSID)
|
||||
{
|
||||
while(i+1<count)
|
||||
{
|
||||
pod.HookedDSs[i] = pod.HookedDSs[i+1];
|
||||
}
|
||||
pod.HookedDSs[i] = 0;
|
||||
s_iHookCount--;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Should never get here. It means we are trying to
|
||||
// remove a DS that was never hooked.
|
||||
kLOG((kLOGERR,"Trying to removing a hook for a DSID (%d) that was never added.", DSID ));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The undocumented LdrGetProcedureAddress...
|
||||
* @param[in] PHMODULE ModuleHandle we're using to get a function pointer
|
||||
* @param[in_opt] PANSI_STRING FunctionName of thing we're trying to find
|
||||
* @param[in_opt] WORD Ordinal, or the number of the things we're trying to find
|
||||
* @param[out] PVOID *FunctionAddress being sent back to the caller
|
||||
* @return DWORD
|
||||
*/
|
||||
DWORD NTAPI LocalLdrGetProcedureAddress
|
||||
(
|
||||
__in HMODULE ModuleHandle,
|
||||
__in_opt PANSI_STRING FunctionName,
|
||||
__in_opt WORD Ordinal,
|
||||
__out PVOID *FunctionAddress
|
||||
)
|
||||
{
|
||||
// See if the caller is asking for TWAIN_32.DLL, and if so, then dive in
|
||||
// and return our DSM_Entry. This works because attempts to load the
|
||||
// same DLL more than once just bump up the reference count. Or put
|
||||
// another way, if function A does a LoadLibrary("xyz") and then function
|
||||
// B does a LoadLibrary("xzy") the HMODULE values returned will be found
|
||||
// to be the same.
|
||||
//
|
||||
// We don't have to check the FunctionName or the Ordinal, there's only
|
||||
// one possible return from TWAIN_32.DLL (thank you initial designers),
|
||||
// and I haven't throught of a good security reason why I need to bother
|
||||
// checking...
|
||||
if (ModuleHandle == s_hmoduleTWAIN32)
|
||||
{
|
||||
// Get and store the original address in case we need it
|
||||
(OriginalLdrGetProcedureAddress(ModuleHandle,FunctionName,Ordinal,(PVOID*)&TWAIN32_DSMEntry));
|
||||
// Return the address to our own function
|
||||
*FunctionAddress = ::DSM_HookedEntry;
|
||||
return (ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
// Otherwise let the call continue unmolested...
|
||||
return (OriginalLdrGetProcedureAddress(ModuleHandle,FunctionName,Ordinal,FunctionAddress));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The undocumented LdrGetProcedureAddressForCaller...
|
||||
* @param[in] PHMODULE ModuleHandle we're using to get a function pointer
|
||||
* @param[in_opt] PANSI_STRING FunctionName of thing we're trying to find
|
||||
* @param[in_opt] WORD Ordinal, or the number of the things we're trying to find
|
||||
* @param[out] PVOID *FunctionAddress being sent back to the caller
|
||||
* @param[in] BOOL bValue
|
||||
* @param[in] PVOID *CallbackAddress
|
||||
* @return DWORD
|
||||
*/
|
||||
DWORD NTAPI LocalLdrGetProcedureAddressForCaller
|
||||
(
|
||||
__in HMODULE ModuleHandle,
|
||||
__in_opt PANSI_STRING FunctionName,
|
||||
__in_opt WORD Ordinal,
|
||||
__out PVOID *FunctionAddress,
|
||||
__in BOOL bValue,
|
||||
__in PVOID *CallbackAddress
|
||||
)
|
||||
{
|
||||
// See if the caller is asking for TWAIN_32.DLL, and if so, then dive in
|
||||
// and return our DSM_Entry. This works because attempts to load the
|
||||
// same DLL more than once just bump up the reference count. Or put
|
||||
// another way, if function A does a LoadLibrary("xyz") and then function
|
||||
// B does a LoadLibrary("xzy") the HMODULE values returned will be found
|
||||
// to be the same.
|
||||
//
|
||||
// We don't have to check the FunctionName or the Ordinal, there's only
|
||||
// one possible return from TWAIN_32.DLL (thank you initial designers),
|
||||
// and I haven't throught of a good security reason why I need to bother
|
||||
// checking...
|
||||
if (ModuleHandle == s_hmoduleTWAIN32)
|
||||
{
|
||||
// Get and store the original address in case we need it
|
||||
(OriginalLdrGetProcedureAddressForCaller(ModuleHandle,FunctionName,Ordinal,(PVOID*)&TWAIN32_DSMEntry,bValue,CallbackAddress));
|
||||
// Return the address to our own function
|
||||
*FunctionAddress = ::DSM_HookedEntry;
|
||||
return (ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
// Otherwise let the call continue unmolested...
|
||||
return (OriginalLdrGetProcedureAddressForCaller(ModuleHandle,FunctionName,Ordinal,FunctionAddress,bValue,CallbackAddress));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Install the hooks and load the library, if hooks are already installed,
|
||||
* then just load the library...
|
||||
*/
|
||||
HMODULE InstallTwain32DllHooks
|
||||
(
|
||||
const char* const _lib,
|
||||
const bool _hook,
|
||||
const TW_UINT32 _DSID
|
||||
)
|
||||
{
|
||||
HMODULE hmodule;
|
||||
CTwHook *ptwhook;
|
||||
DWORD dwResult;
|
||||
|
||||
// Init stuff...
|
||||
ptwhook = (CTwHook*)NULL;
|
||||
|
||||
// We hook before we load the library so that we can intercept calls
|
||||
// to the Ldr functions during DllMain. But we only do the hook if
|
||||
// it's the first time we've been here, and we've been asked to do
|
||||
// hooking (which we won't be if the DSM is doing GetFirst/GetNext to
|
||||
// enumerate the drivers)...
|
||||
if (_hook)
|
||||
{
|
||||
// If we already have a hook in place, then bump up our
|
||||
// reference counter...
|
||||
if ( (s_iHookCount > 0)
|
||||
&& ((CTwHook*)NULL != s_ptwhook))
|
||||
{
|
||||
s_ptwhook->Hook_Add_DSID(_DSID);
|
||||
}
|
||||
|
||||
// Otherwise load the beastie...
|
||||
else
|
||||
{
|
||||
// Allocate our object...
|
||||
s_iHookCount = 0;
|
||||
ptwhook = new CTwHook();
|
||||
if (ptwhook)
|
||||
{
|
||||
// Do the hook...
|
||||
if (ptwhook->Hook(HOOK_ATTACH))
|
||||
{
|
||||
// This activates our hooking functions to look for
|
||||
// attempts to get DSM_Entry...
|
||||
s_ptwhook = ptwhook;
|
||||
s_ptwhook->Hook_Add_DSID(_DSID);
|
||||
}
|
||||
// No joy, cleanup...
|
||||
else
|
||||
{
|
||||
delete ptwhook;
|
||||
ptwhook = (CTwHook*)NULL;
|
||||
s_ptwhook = (CTwHook*)NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load the library the caller asked for...
|
||||
hmodule = ::LoadLibrary(_lib);
|
||||
|
||||
// If we hooked for this module, and the LoadLibrary failed, then
|
||||
// undo the hook...
|
||||
if ( (NULL == hmodule)
|
||||
&& ((CTwHook*)NULL != ptwhook)
|
||||
&& _hook)
|
||||
{
|
||||
dwResult = ::GetLastError();
|
||||
s_ptwhook->Hook_Remove_DSID(_DSID);
|
||||
if (s_iHookCount <= 0)
|
||||
{
|
||||
s_ptwhook = (CTwHook*)NULL;
|
||||
delete ptwhook;
|
||||
s_iHookCount = 0;
|
||||
}
|
||||
::SetLastError(dwResult);
|
||||
}
|
||||
|
||||
// All done...
|
||||
return(hmodule);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Uninstall the hooks (if needed), and free the library, if hooks are not currently
|
||||
* installed, then just free the library...
|
||||
*/
|
||||
BOOL UninstallTwain32DllHooks
|
||||
(
|
||||
const HMODULE _hmodule,
|
||||
const bool _unhook,
|
||||
const TW_UINT32 _DSID
|
||||
)
|
||||
{
|
||||
if(_unhook)
|
||||
{
|
||||
if (s_ptwhook)
|
||||
{
|
||||
// Remove the DS from the list and decrement the count...
|
||||
s_ptwhook->Hook_Remove_DSID(_DSID);
|
||||
|
||||
// If we're at zero, then cleanup. I'm probably being a bit
|
||||
// paranoid about the cleanup scheme, but I like being paranoid
|
||||
// when it comes to hooks...
|
||||
if (s_iHookCount <= 0)
|
||||
{
|
||||
CTwHook *ptwhook = s_ptwhook;
|
||||
s_ptwhook = (CTwHook*)NULL;
|
||||
delete ptwhook;
|
||||
s_iHookCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Free the library...
|
||||
return(::FreeLibrary(_hmodule));
|
||||
}
|
||||
|
||||
|
||||
|
||||
// TWDSM_OS_64BIT/TWNDSM_OS_32BIT
|
||||
#else
|
||||
#error error, we need to be either 32-bit or 64-bit...
|
||||
#endif
|
|
@ -0,0 +1,305 @@
|
|||
/***************************************************************************
|
||||
* TWAIN Data Source Manager version 2.1
|
||||
* Manages image acquisition data sources used by a machine.
|
||||
* Copyright © 2007 TWAIN Working Group:
|
||||
* Adobe Systems Incorporated,AnyDoc Software Inc., Eastman Kodak Company,
|
||||
* Fujitsu Computer Products of America, JFL Peripheral Solutions Inc.,
|
||||
* Ricoh Corporation, and Xerox Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Contact the TWAIN Working Group by emailing the Technical Subcommittee at
|
||||
* twainwg@twain.org or mailing us at 13090 Hwy 9, Suite 3, Boulder Creek, CA 95006.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/**
|
||||
* @file log.cpp
|
||||
* Log messages.
|
||||
* Provide logging for the messages to and from the Data Source Manager.
|
||||
* @author TWAIN Working Group
|
||||
* @date March 2007
|
||||
*/
|
||||
|
||||
#include "dsm.h"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Enviroment varible of path to where to write the LogFile name.
|
||||
* @see CTwnDsmLog
|
||||
*/
|
||||
#define kLOGENV "TWAINDSM_LOG"
|
||||
|
||||
/**
|
||||
* Enviroment varible of the fopen logmode to use (if you need to
|
||||
* grow the log). The default behavior is to wipe it clean each time
|
||||
* we start up...
|
||||
* @see CTwnDsmLog
|
||||
*/
|
||||
#define kLOGMODEENV "TWAINDSM_LOGMODE"
|
||||
|
||||
/**
|
||||
* Maximum message length we can handle...
|
||||
* @see CTwnDsmLog
|
||||
*/
|
||||
#define TWNDSM_MAX_MSG 1024
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Our implementation class where we hide our attributes...
|
||||
*/
|
||||
class CTwnDsmLogImpl
|
||||
{
|
||||
public:
|
||||
/// Make sure we're squeaky clean...
|
||||
CTwnDsmLogImpl()
|
||||
{
|
||||
memset(&pod,0,sizeof(pod));
|
||||
}
|
||||
|
||||
public:
|
||||
// If you add a class in future, (and I can't imagine why you
|
||||
// would) declare it here and not in the pod, or the memset
|
||||
// we do in the constructor will ruin your day...
|
||||
|
||||
/**
|
||||
* We use a pod system because it help prevents us from
|
||||
* making dumb initialization mistakes...
|
||||
*/
|
||||
struct _pod
|
||||
{
|
||||
FILE *m_plog; /**< where we'll dump information. */
|
||||
char *m_message; /**< buffer for our messages. */
|
||||
char m_logpath[FILENAME_MAX]; /**< where we put the file. */
|
||||
char m_logmode[16]; /**< how we fopen the file. */
|
||||
int m_nIndent; /**< how far to indent the log message */
|
||||
} pod; /**< Pieces of data for CTwnDsmAppsImpl*/
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The constructor for our class. This is where we see if we have a
|
||||
* file in the TWAINDSM_LOG environment variable. If so, then we'll
|
||||
* log stuff. If not, then we'll log nothing. TWAINDSM_LOGMODE
|
||||
* selects how we open the file. The default value is "w+", which
|
||||
* means it's wiped out each time a new session is started. Setting
|
||||
* this environmental to "a+" will cause the log information to be
|
||||
* appended to an existing file (a new one will still be created if
|
||||
* needed...
|
||||
*/
|
||||
CTwnDsmLog::CTwnDsmLog()
|
||||
{
|
||||
// Init stuff...
|
||||
m_ptwndsmlogimpl = new CTwnDsmLogImpl;
|
||||
|
||||
// see if a logfile is to be used
|
||||
SGETENV(m_ptwndsmlogimpl->pod.m_logpath,NCHARS(m_ptwndsmlogimpl->pod.m_logpath),kLOGENV);
|
||||
|
||||
// If we have a path, then get our mode...
|
||||
if (m_ptwndsmlogimpl->pod.m_logpath[0])
|
||||
{
|
||||
SGETENV(m_ptwndsmlogimpl->pod.m_logmode,NCHARS(m_ptwndsmlogimpl->pod.m_logmode),kLOGMODEENV);
|
||||
if (!m_ptwndsmlogimpl->pod.m_logmode[0])
|
||||
{
|
||||
// The default is to wipe the log clean...
|
||||
SSTRCPY(m_ptwndsmlogimpl->pod.m_logmode,sizeof(m_ptwndsmlogimpl->pod.m_logmode),"w");
|
||||
}
|
||||
|
||||
// Only bother to allocate a buffer if logging is on...
|
||||
m_ptwndsmlogimpl->pod.m_message = (char*)calloc(TWNDSM_MAX_MSG,1);
|
||||
if (!m_ptwndsmlogimpl->pod.m_message)
|
||||
{
|
||||
kPANIC("Unable to allocate a buffer for logging...");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The destructor for our class. Make sure the log is closed,
|
||||
* free the buffer and destroy our implementation class...
|
||||
*/
|
||||
CTwnDsmLog::~CTwnDsmLog()
|
||||
{
|
||||
if (m_ptwndsmlogimpl)
|
||||
{
|
||||
if (m_ptwndsmlogimpl->pod.m_plog)
|
||||
{
|
||||
fclose(m_ptwndsmlogimpl->pod.m_plog);
|
||||
}
|
||||
if (m_ptwndsmlogimpl->pod.m_message)
|
||||
{
|
||||
free(m_ptwndsmlogimpl->pod.m_message);
|
||||
}
|
||||
delete m_ptwndsmlogimpl;
|
||||
m_ptwndsmlogimpl = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Logging function.
|
||||
*
|
||||
* We provide a timestamp from hours to milliseconds, which can be
|
||||
* used to help with performance, and to detect large, unexpected
|
||||
* idle times. The filename and line number in the source code is
|
||||
* provided. GetLastError or errno may offer a hint about a problem
|
||||
* with a system call, but be careful, since it's not cleared and so
|
||||
* it may report a message that has nothing to do with the current
|
||||
* calls, or anything going on in the DSM. The id of the thread that
|
||||
* called us is useful for finding problems with unsafe use, or use
|
||||
* that crosses thread boundaries in a bad way (like on Windows, when
|
||||
* one has to stay in the same thread as the HWND if the DAT_NULL
|
||||
* messages are going to work)...
|
||||
*/
|
||||
void CTwnDsmLog::Log(const int _doassert,
|
||||
const char* const _file,
|
||||
const int _line,
|
||||
const char* const _format,
|
||||
...)
|
||||
{
|
||||
// We've nothing to do, so bail...
|
||||
if (0 == m_ptwndsmlogimpl->pod.m_logpath[0])
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Okay, now use the stack...
|
||||
UINT nError = 0;
|
||||
UINT nChars = 0;
|
||||
char *message = NULL;
|
||||
const char *file = NULL;
|
||||
|
||||
// Grab the system error, this can be really useful...
|
||||
#if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
|
||||
nError = GetLastError();
|
||||
if (nError == 0)
|
||||
{
|
||||
// Yeah, yeah...this is dumb, but I like a clean prefast log... :)
|
||||
nError = 0;
|
||||
}
|
||||
#elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
|
||||
nError = errno;
|
||||
#else
|
||||
#error Sorry, we do not recognize this system...
|
||||
#endif
|
||||
|
||||
// If we have no log yet, try to get one...
|
||||
if (0 == m_ptwndsmlogimpl->pod.m_plog)
|
||||
{
|
||||
FOPEN(m_ptwndsmlogimpl->pod.m_plog,m_ptwndsmlogimpl->pod.m_logpath,m_ptwndsmlogimpl->pod.m_logmode);
|
||||
if (0 == m_ptwndsmlogimpl->pod.m_plog)
|
||||
{
|
||||
fprintf(stderr,"DSM: Error - logging has been disabled because logfile could not be opened: file=<%s>, mode=<%s>, errno=%d\r\n",m_ptwndsmlogimpl->pod.m_logpath,m_ptwndsmlogimpl->pod.m_logmode,errno);
|
||||
m_ptwndsmlogimpl->pod.m_logpath[0] = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Trim the filename down to just the filename, no path...
|
||||
file = 0;
|
||||
#if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
|
||||
// Only look for this on Windows...
|
||||
file = strrchr(_file,'\\');
|
||||
#endif
|
||||
if (!file)
|
||||
{
|
||||
// If we didn't find a backslash, try a forward slash...
|
||||
file = strrchr(_file,'/');
|
||||
}
|
||||
if (file)
|
||||
{
|
||||
// skip the slash...
|
||||
file = &file[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Couldn't find any slashes...
|
||||
file = (char*)_file;
|
||||
}
|
||||
|
||||
// Build the message header...
|
||||
#if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
|
||||
SYSTEMTIME st;
|
||||
GetLocalTime(&st);
|
||||
nChars = SNPRINTF(m_ptwndsmlogimpl->pod.m_message,
|
||||
TWNDSM_MAX_MSG,
|
||||
#if (TWNDSM_CMP_VERSION >= 1400)
|
||||
TWNDSM_MAX_MSG,
|
||||
#endif
|
||||
"[%02d%02d%02d%03d %-8s %4d %5u %p] %.*s",
|
||||
(int)st.wHour, (int)st.wMinute, (int)st.wSecond,(int)st.wMilliseconds,
|
||||
file, (int)_line,
|
||||
nError,
|
||||
(void*)(UINT_PTR)GETTHREADID(),
|
||||
m_ptwndsmlogimpl->pod.m_nIndent*2, " ");
|
||||
#elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
|
||||
timeval tv;
|
||||
tm tm;
|
||||
gettimeofday(&tv,NULL);
|
||||
tzset();
|
||||
localtime_r(&tv.tv_sec,&tm);
|
||||
nChars = SNPRINTF(m_ptwndsmlogimpl->pod.m_message,
|
||||
TWNDSM_MAX_MSG,
|
||||
"[%02d%02d%02d%03d %-8s %4d %5d %p] %.*s",
|
||||
tm.tm_hour,tm.tm_min,tm.tm_sec,(int)(tv.tv_usec / 1000),
|
||||
file,_line,
|
||||
nError,
|
||||
(void*)GETTHREADID(),
|
||||
m_ptwndsmlogimpl->pod.m_nIndent*2, " ");
|
||||
|
||||
#else
|
||||
#error Sorry, we do not recognize this system...
|
||||
#endif
|
||||
|
||||
// This is the room remaining in the buffer, with room for a null...
|
||||
nChars = (TWNDSM_MAX_MSG - nChars) - 1;
|
||||
message = &m_ptwndsmlogimpl->pod.m_message[strlen(m_ptwndsmlogimpl->pod.m_message)];
|
||||
|
||||
// Finally, tack on the user portion of the message...
|
||||
va_list valist;
|
||||
va_start(valist,_format);
|
||||
#if (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP) && (TWNDSM_CMP_VERSION >= 1400)
|
||||
_vsnprintf_s(message,nChars,nChars,_format,valist);
|
||||
#elif (TWNDSM_CMP == TWNDSM_CMP_VISUALCPP)
|
||||
_vsnprintf(message,nChars,_format,valist);
|
||||
#elif (TWNDSM_CMP == TWNDSM_CMP_GNUGPP)
|
||||
vsnprintf(message,nChars,_format,valist);
|
||||
#else
|
||||
#error Sorry, we do not recognize this system...
|
||||
#endif
|
||||
va_end(valist);
|
||||
|
||||
// Write the message...
|
||||
fprintf(m_ptwndsmlogimpl->pod.m_plog,"%s\r\n",m_ptwndsmlogimpl->pod.m_message);
|
||||
fflush(m_ptwndsmlogimpl->pod.m_plog);
|
||||
|
||||
// Do the assert, if asked for...
|
||||
if (_doassert)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
void CTwnDsmLog::Indent(int nChange)
|
||||
{
|
||||
m_ptwndsmlogimpl->pod.m_nIndent += nChange;
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,31 @@
|
|||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by dsm.rc
|
||||
//
|
||||
// Determine what bit verison of OS we are using
|
||||
#if defined(WIN64) || defined(__x86_64__) || defined(__LP64__) || defined(_M_X64) || defined(_M_IA64)
|
||||
#define TWNDSM_OS_BIT_STR "64"
|
||||
#else
|
||||
#define TWNDSM_OS_BIT_STR "32"
|
||||
#endif
|
||||
//
|
||||
// Identity information that we'll toss into the log and into the version
|
||||
// resource on Windows...
|
||||
//
|
||||
#define TWNDSM_ORGANIZATION "TWAIN Working Group"
|
||||
#define TWNDSM_DESCRIPTION "TWAIN " TWNDSM_OS_BIT_STR " Source Manager (Image Acquisition Interface)"
|
||||
#define TWNDSM_VERSION_NUM 2, 5, 0, 0
|
||||
#define TWNDSM_VERSION_STR "2, 5, 0, 0"
|
||||
#define ID_LST_SOURCES 10
|
||||
#define IDC_STATIC 11
|
||||
#define IDD_DLG_SOURCE 101
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 102
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1003
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue