From 51414ad136e1226c881de2b736efdedf1a541898 Mon Sep 17 00:00:00 2001 From: Eugene Wang <8755753+soukoku@users.noreply.github.com> Date: Thu, 8 Jan 2026 21:20:58 -0500 Subject: [PATCH] Major revamp for beta, with simplified initialization and no winform/wpf dependency. --- LICENSE.txt | 2 +- NTwain4.sln | 160 - NTwain4.slnx | 30 + README.md | 13 +- csizes/WM_Constants.txt | 372 + samples/ConsoleSample/ConsoleSample.csproj | 20 + samples/ConsoleSample/Program.cs | 146 + samples/ConsoleSample/app.manifest | 65 + .../KodakTester.csproj} | 2 +- .../MainForm.Designer.cs | 128 +- samples/KodakTester/MainForm.cs | 586 ++ .../MainForm.resx | 0 samples/KodakTester/Program.cs | 16 + samples/ScannerTester/MainForm.cs | 591 -- samples/ScannerTester/Program.cs | 17 - samples/WinConsole32/Program.cs | 243 - samples/WinConsole32/WinConsole32.csproj | 21 - samples/WinForm32/ControlExtensions.cs | 11 +- samples/WinForm32/Form1.cs | 99 +- samples/WinForm32/NoOpStream.cs | 11 +- samples/WinForm32/Program.cs | 63 +- samples/WinForm32/WinForm32.csproj | 5 +- .../runtimes/win-x86/native/TWAINDSM.dll | Bin 0 -> 176544 bytes samples/WinForm64/WinForm64.csproj | 2 +- src/Directory.Build.props | 9 +- src/NTwain/DSM/DSMGenerator.tt | 14 +- src/NTwain/DSM/DsmLoader.cs | 111 +- src/NTwain/DSM/Linux64DSM.cs | 14 +- src/NTwain/DSM/LinuxBotched64DSM.cs | 14 +- src/NTwain/DSM/LinuxDSM.cs | 14 +- src/NTwain/DSM/OSXLegacyDSM.cs | 14 +- src/NTwain/DSM/OSXNewDSM.cs | 14 +- src/NTwain/DSM/WinLegacyDSM.cs | 14 +- src/NTwain/DSM/WinNewDSM.cs | 14 +- src/NTwain/Data/BufferedData.cs | 47 +- src/NTwain/Data/README.md | 11 - src/NTwain/Data/SizeAndConversionUtils.cs | 24 +- src/NTwain/Data/TWAINH.cs | 9079 ++++++++--------- src/NTwain/Data/TWAINH_EXTRAS.cs | 2301 +++-- src/NTwain/Data/ValueReader.cs | 1457 ++- src/NTwain/Data/ValueWriter.cs | 1185 ++- src/NTwain/Events/EventHandler.cs | 12 + src/NTwain/Events/TransferErrorEventArgs.cs | 48 + src/NTwain/Events/TransferReadyEventArgs.cs | 139 + .../{ => Events}/TransferredEventArgs.cs | 35 +- src/NTwain/IMemoryManager.cs | 36 +- src/NTwain/Imaging/BITMAP.cs | 253 + src/NTwain/Imaging/ImageTools.cs | 145 + src/NTwain/{Native => Imaging}/TIFF.cs | 34 +- src/NTwain/MessagePumpThread.cs | 173 - src/NTwain/NTwain.csproj | 16 +- src/NTwain/Native/BITMAP.cs | 254 - src/NTwain/Native/ImageTools.cs | 146 - src/NTwain/Native/WIN_MESSAGE.cs | 21 - src/NTwain/Native/WinNativeMethods.cs | 97 - src/NTwain/NativeMethods.json | 4 - src/NTwain/NativeMethods.txt | 25 + src/NTwain/Platform/DllPath.cs | 38 + src/NTwain/Platform/FallbackMemoryManager.cs | 35 + src/NTwain/Platform/TwainMemoryManager.cs | 51 + src/NTwain/Platform/Win32MemoryManager.cs | 49 + src/NTwain/Platform/Win32MessagePump.cs | 521 + src/NTwain/{ => Polyfills}/CompilerTypes.cs | 15 +- src/NTwain/Polyfills/OperatingSystem.cs | 103 + src/NTwain/SourceEnableOption.cs | 24 + src/NTwain/TWAINWorkingGroup/NativeMethods.cs | 1140 +-- src/NTwain/TWAINWorkingGroup/TWAIN.cs | 16 +- src/NTwain/TransferCanceledEventArgs.cs | 10 - src/NTwain/TransferErrorEventArgs.cs | 47 - src/NTwain/TransferLoopThread.Logic.cs | 553 + src/NTwain/TransferLoopThread.cs | 99 + src/NTwain/TransferReadyEventArgs.cs | 114 - .../Triplets/AudioDATs/AudioFileXfer.cs | 63 +- src/NTwain/Triplets/AudioDATs/AudioInfo.cs | 65 +- .../Triplets/AudioDATs/AudioNativeXfer.cs | 65 +- src/NTwain/Triplets/ControlDATs/Callback.cs | 57 +- src/NTwain/Triplets/ControlDATs/Callback2.cs | 57 +- src/NTwain/Triplets/ControlDATs/Capability.cs | 103 +- .../Triplets/ControlDATs/CapabilityCustom.cs | 99 +- .../Triplets/ControlDATs/CustomDsData.cs | 67 +- .../Triplets/ControlDATs/DeviceEvent.cs | 59 +- src/NTwain/Triplets/ControlDATs/EntryPoint.cs | 116 +- src/NTwain/Triplets/ControlDATs/Event.cs | 57 +- src/NTwain/Triplets/ControlDATs/FileSystem.cs | 103 +- src/NTwain/Triplets/ControlDATs/Identity.cs | 98 +- src/NTwain/Triplets/ControlDATs/Metrics.cs | 65 +- src/NTwain/Triplets/ControlDATs/Parent.cs | 76 +- src/NTwain/Triplets/ControlDATs/Passthru.cs | 57 +- .../Triplets/ControlDATs/PendingXfers.cs | 73 +- .../Triplets/ControlDATs/SetupFileXfer.cs | 79 +- .../Triplets/ControlDATs/SetupMemXfer.cs | 59 +- src/NTwain/Triplets/ControlDATs/Status.cs | 104 +- src/NTwain/Triplets/ControlDATs/StatusUtf8.cs | 58 +- .../Triplets/ControlDATs/TwainDirect.cs | 63 +- .../Triplets/ControlDATs/UserInterface.cs | 69 +- src/NTwain/Triplets/ControlDATs/XferGroup.cs | 67 +- src/NTwain/Triplets/DGAudio.cs | 13 +- src/NTwain/Triplets/ImageDATs/CieColor.cs | 65 +- src/NTwain/Triplets/ImageDATs/ExtImageInfo.cs | 24 +- src/NTwain/Triplets/ImageDATs/Filter.cs | 79 +- src/NTwain/Triplets/ImageDATs/GrayResponse.cs | 67 +- src/NTwain/Triplets/ImageDATs/IccProfile.cs | 65 +- .../Triplets/ImageDATs/ImageFileXfer.cs | 63 +- src/NTwain/Triplets/ImageDATs/ImageInfo.cs | 65 +- src/NTwain/Triplets/ImageDATs/ImageLayout.cs | 79 +- .../Triplets/ImageDATs/ImageMemFileXfer.cs | 63 +- src/NTwain/Triplets/ImageDATs/ImageMemXfer.cs | 63 +- .../Triplets/ImageDATs/ImageNativeXfer.cs | 65 +- .../Triplets/ImageDATs/JpegCompression.cs | 79 +- src/NTwain/Triplets/ImageDATs/Palette8.cs | 79 +- src/NTwain/Triplets/ImageDATs/RgbResponse.cs | 67 +- src/NTwain/TwainAppSession.Callback.cs | 177 + src/NTwain/TwainAppSession.Callbacks.cs | 141 - src/NTwain/TwainAppSession.Caps.cs | 1395 +-- src/NTwain/TwainAppSession.FileSystem.cs | 37 - src/NTwain/TwainAppSession.Memory.cs | 131 - src/NTwain/TwainAppSession.PropEvents.cs | 169 - src/NTwain/TwainAppSession.Sources.cs | 217 - src/NTwain/TwainAppSession.TwainMisc.cs | 101 + src/NTwain/TwainAppSession.TwainState.cs | 570 ++ src/NTwain/TwainAppSession.Windows.cs | 116 - src/NTwain/TwainAppSession.Xfers.cs | 602 -- src/NTwain/TwainAppSession.cs | 469 +- src/NTwain/TwainEventDelegate.cs | 11 - 124 files changed, 14367 insertions(+), 13676 deletions(-) delete mode 100644 NTwain4.sln create mode 100644 NTwain4.slnx create mode 100644 csizes/WM_Constants.txt create mode 100644 samples/ConsoleSample/ConsoleSample.csproj create mode 100644 samples/ConsoleSample/Program.cs create mode 100644 samples/ConsoleSample/app.manifest rename samples/{ScannerTester/ScannerTester.csproj => KodakTester/KodakTester.csproj} (89%) rename samples/{ScannerTester => KodakTester}/MainForm.Designer.cs (71%) create mode 100644 samples/KodakTester/MainForm.cs rename samples/{ScannerTester => KodakTester}/MainForm.resx (100%) create mode 100644 samples/KodakTester/Program.cs delete mode 100644 samples/ScannerTester/MainForm.cs delete mode 100644 samples/ScannerTester/Program.cs delete mode 100644 samples/WinConsole32/Program.cs delete mode 100644 samples/WinConsole32/WinConsole32.csproj create mode 100644 samples/WinForm32/runtimes/win-x86/native/TWAINDSM.dll delete mode 100644 src/NTwain/Data/README.md create mode 100644 src/NTwain/Events/EventHandler.cs create mode 100644 src/NTwain/Events/TransferErrorEventArgs.cs create mode 100644 src/NTwain/Events/TransferReadyEventArgs.cs rename src/NTwain/{ => Events}/TransferredEventArgs.cs (76%) create mode 100644 src/NTwain/Imaging/BITMAP.cs create mode 100644 src/NTwain/Imaging/ImageTools.cs rename src/NTwain/{Native => Imaging}/TIFF.cs (87%) delete mode 100644 src/NTwain/MessagePumpThread.cs delete mode 100644 src/NTwain/Native/BITMAP.cs delete mode 100644 src/NTwain/Native/ImageTools.cs delete mode 100644 src/NTwain/Native/WIN_MESSAGE.cs delete mode 100644 src/NTwain/Native/WinNativeMethods.cs delete mode 100644 src/NTwain/NativeMethods.json create mode 100644 src/NTwain/Platform/DllPath.cs create mode 100644 src/NTwain/Platform/FallbackMemoryManager.cs create mode 100644 src/NTwain/Platform/TwainMemoryManager.cs create mode 100644 src/NTwain/Platform/Win32MemoryManager.cs create mode 100644 src/NTwain/Platform/Win32MessagePump.cs rename src/NTwain/{ => Polyfills}/CompilerTypes.cs (88%) create mode 100644 src/NTwain/Polyfills/OperatingSystem.cs create mode 100644 src/NTwain/SourceEnableOption.cs delete mode 100644 src/NTwain/TransferCanceledEventArgs.cs delete mode 100644 src/NTwain/TransferErrorEventArgs.cs create mode 100644 src/NTwain/TransferLoopThread.Logic.cs create mode 100644 src/NTwain/TransferLoopThread.cs delete mode 100644 src/NTwain/TransferReadyEventArgs.cs create mode 100644 src/NTwain/TwainAppSession.Callback.cs delete mode 100644 src/NTwain/TwainAppSession.Callbacks.cs delete mode 100644 src/NTwain/TwainAppSession.FileSystem.cs delete mode 100644 src/NTwain/TwainAppSession.Memory.cs delete mode 100644 src/NTwain/TwainAppSession.PropEvents.cs delete mode 100644 src/NTwain/TwainAppSession.Sources.cs create mode 100644 src/NTwain/TwainAppSession.TwainMisc.cs create mode 100644 src/NTwain/TwainAppSession.TwainState.cs delete mode 100644 src/NTwain/TwainAppSession.Windows.cs delete mode 100644 src/NTwain/TwainAppSession.Xfers.cs delete mode 100644 src/NTwain/TwainEventDelegate.cs diff --git a/LICENSE.txt b/LICENSE.txt index cbedf08..b787503 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -2,7 +2,7 @@ The MIT License (MIT) -Copyright (c) 2012 - 2023 Eugene Wang +Copyright (c) 2012 - 2026 Eugene Wang Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/NTwain4.sln b/NTwain4.sln deleted file mode 100644 index 7cfaa23..0000000 --- a/NTwain4.sln +++ /dev/null @@ -1,160 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.1.32414.318 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_common", "_common", "{4CE0B9ED-2CD1-440F-B4EC-35ECA6D61EFE}" - ProjectSection(SolutionItems) = preProject - .gitignore = .gitignore - Build.cmd = Build.cmd - src\Directory.Build.props = src\Directory.Build.props - LICENSE.txt = LICENSE.txt - README.md = README.md - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{707B4313-8EF8-4D0F-A95E-590783422187}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_twain-doc", "_twain-doc", "{0C94E5AD-E226-4A30-92B4-C28FE5B7FC23}" - ProjectSection(SolutionItems) = preProject - twain-doc\TWAIN-2.5-Features.pdf = twain-doc\TWAIN-2.5-Features.pdf - twain-doc\TWAIN-2.5-Specification.pdf = twain-doc\TWAIN-2.5-Specification.pdf - twain-doc\twain2.5.h = twain-doc\twain2.5.h - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NTwain", "src\NTwain\NTwain.csproj", "{3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinForm32", "samples\WinForm32\WinForm32.csproj", "{7792A94E-D0B4-440D-8BD5-CA1CA548782C}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinForm64", "samples\WinForm64\WinForm64.csproj", "{C9666CB2-C9A6-48C8-AB51-D616A48058A7}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "csizes", "csizes\csizes.vcxproj", "{1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinConsole32", "samples\WinConsole32\WinConsole32.csproj", "{4E2417E7-FDC3-46D7-B976-84A97B500B74}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScannerTester", "samples\ScannerTester\ScannerTester.csproj", "{EEFDA89D-7E11-7609-5383-FA1ADEA88CF4}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|ARM64 = Debug|ARM64 - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|ARM64 = Release|ARM64 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Debug|ARM64.ActiveCfg = Debug|Any CPU - {3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Debug|ARM64.Build.0 = Debug|Any CPU - {3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Debug|x64.ActiveCfg = Debug|Any CPU - {3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Debug|x64.Build.0 = Debug|Any CPU - {3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Debug|x86.ActiveCfg = Debug|Any CPU - {3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Debug|x86.Build.0 = Debug|Any CPU - {3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Release|Any CPU.Build.0 = Release|Any CPU - {3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Release|ARM64.ActiveCfg = Release|Any CPU - {3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Release|ARM64.Build.0 = Release|Any CPU - {3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Release|x64.ActiveCfg = Release|Any CPU - {3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Release|x64.Build.0 = Release|Any CPU - {3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Release|x86.ActiveCfg = Release|Any CPU - {3C8A3CF9-A60D-4F21-B866-D291A7AABD4A}.Release|x86.Build.0 = Release|Any CPU - {7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Debug|ARM64.ActiveCfg = Debug|Any CPU - {7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Debug|ARM64.Build.0 = Debug|Any CPU - {7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Debug|x64.ActiveCfg = Debug|Any CPU - {7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Debug|x64.Build.0 = Debug|Any CPU - {7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Debug|x86.ActiveCfg = Debug|Any CPU - {7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Debug|x86.Build.0 = Debug|Any CPU - {7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Release|Any CPU.Build.0 = Release|Any CPU - {7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Release|ARM64.ActiveCfg = Release|Any CPU - {7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Release|ARM64.Build.0 = Release|Any CPU - {7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Release|x64.ActiveCfg = Release|Any CPU - {7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Release|x64.Build.0 = Release|Any CPU - {7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Release|x86.ActiveCfg = Release|Any CPU - {7792A94E-D0B4-440D-8BD5-CA1CA548782C}.Release|x86.Build.0 = Release|Any CPU - {C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Debug|ARM64.ActiveCfg = Debug|Any CPU - {C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Debug|ARM64.Build.0 = Debug|Any CPU - {C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Debug|x64.ActiveCfg = Debug|Any CPU - {C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Debug|x64.Build.0 = Debug|Any CPU - {C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Debug|x86.ActiveCfg = Debug|Any CPU - {C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Debug|x86.Build.0 = Debug|Any CPU - {C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Release|Any CPU.Build.0 = Release|Any CPU - {C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Release|ARM64.ActiveCfg = Release|Any CPU - {C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Release|ARM64.Build.0 = Release|Any CPU - {C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Release|x64.ActiveCfg = Release|Any CPU - {C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Release|x64.Build.0 = Release|Any CPU - {C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Release|x86.ActiveCfg = Release|Any CPU - {C9666CB2-C9A6-48C8-AB51-D616A48058A7}.Release|x86.Build.0 = Release|Any CPU - {1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Debug|Any CPU.ActiveCfg = Debug|x64 - {1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Debug|Any CPU.Build.0 = Debug|x64 - {1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Debug|ARM64.ActiveCfg = Debug|x64 - {1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Debug|ARM64.Build.0 = Debug|x64 - {1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Debug|x64.ActiveCfg = Debug|x64 - {1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Debug|x64.Build.0 = Debug|x64 - {1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Debug|x86.ActiveCfg = Debug|Win32 - {1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Debug|x86.Build.0 = Debug|Win32 - {1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Release|Any CPU.ActiveCfg = Release|x64 - {1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Release|Any CPU.Build.0 = Release|x64 - {1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Release|ARM64.ActiveCfg = Release|x64 - {1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Release|ARM64.Build.0 = Release|x64 - {1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Release|x64.ActiveCfg = Release|x64 - {1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Release|x64.Build.0 = Release|x64 - {1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Release|x86.ActiveCfg = Release|Win32 - {1AABD2DC-3F81-4301-938B-3EC2EDEF38D4}.Release|x86.Build.0 = Release|Win32 - {4E2417E7-FDC3-46D7-B976-84A97B500B74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4E2417E7-FDC3-46D7-B976-84A97B500B74}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4E2417E7-FDC3-46D7-B976-84A97B500B74}.Debug|ARM64.ActiveCfg = Debug|Any CPU - {4E2417E7-FDC3-46D7-B976-84A97B500B74}.Debug|ARM64.Build.0 = Debug|Any CPU - {4E2417E7-FDC3-46D7-B976-84A97B500B74}.Debug|x64.ActiveCfg = Debug|Any CPU - {4E2417E7-FDC3-46D7-B976-84A97B500B74}.Debug|x64.Build.0 = Debug|Any CPU - {4E2417E7-FDC3-46D7-B976-84A97B500B74}.Debug|x86.ActiveCfg = Debug|Any CPU - {4E2417E7-FDC3-46D7-B976-84A97B500B74}.Debug|x86.Build.0 = Debug|Any CPU - {4E2417E7-FDC3-46D7-B976-84A97B500B74}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4E2417E7-FDC3-46D7-B976-84A97B500B74}.Release|Any CPU.Build.0 = Release|Any CPU - {4E2417E7-FDC3-46D7-B976-84A97B500B74}.Release|ARM64.ActiveCfg = Release|Any CPU - {4E2417E7-FDC3-46D7-B976-84A97B500B74}.Release|ARM64.Build.0 = Release|Any CPU - {4E2417E7-FDC3-46D7-B976-84A97B500B74}.Release|x64.ActiveCfg = Release|Any CPU - {4E2417E7-FDC3-46D7-B976-84A97B500B74}.Release|x64.Build.0 = Release|Any CPU - {4E2417E7-FDC3-46D7-B976-84A97B500B74}.Release|x86.ActiveCfg = Release|Any CPU - {4E2417E7-FDC3-46D7-B976-84A97B500B74}.Release|x86.Build.0 = Release|Any CPU - {EEFDA89D-7E11-7609-5383-FA1ADEA88CF4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EEFDA89D-7E11-7609-5383-FA1ADEA88CF4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EEFDA89D-7E11-7609-5383-FA1ADEA88CF4}.Debug|ARM64.ActiveCfg = Debug|Any CPU - {EEFDA89D-7E11-7609-5383-FA1ADEA88CF4}.Debug|ARM64.Build.0 = Debug|Any CPU - {EEFDA89D-7E11-7609-5383-FA1ADEA88CF4}.Debug|x64.ActiveCfg = Debug|Any CPU - {EEFDA89D-7E11-7609-5383-FA1ADEA88CF4}.Debug|x64.Build.0 = Debug|Any CPU - {EEFDA89D-7E11-7609-5383-FA1ADEA88CF4}.Debug|x86.ActiveCfg = Debug|Any CPU - {EEFDA89D-7E11-7609-5383-FA1ADEA88CF4}.Debug|x86.Build.0 = Debug|Any CPU - {EEFDA89D-7E11-7609-5383-FA1ADEA88CF4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EEFDA89D-7E11-7609-5383-FA1ADEA88CF4}.Release|Any CPU.Build.0 = Release|Any CPU - {EEFDA89D-7E11-7609-5383-FA1ADEA88CF4}.Release|ARM64.ActiveCfg = Release|Any CPU - {EEFDA89D-7E11-7609-5383-FA1ADEA88CF4}.Release|ARM64.Build.0 = Release|Any CPU - {EEFDA89D-7E11-7609-5383-FA1ADEA88CF4}.Release|x64.ActiveCfg = Release|Any CPU - {EEFDA89D-7E11-7609-5383-FA1ADEA88CF4}.Release|x64.Build.0 = Release|Any CPU - {EEFDA89D-7E11-7609-5383-FA1ADEA88CF4}.Release|x86.ActiveCfg = Release|Any CPU - {EEFDA89D-7E11-7609-5383-FA1ADEA88CF4}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {7792A94E-D0B4-440D-8BD5-CA1CA548782C} = {707B4313-8EF8-4D0F-A95E-590783422187} - {C9666CB2-C9A6-48C8-AB51-D616A48058A7} = {707B4313-8EF8-4D0F-A95E-590783422187} - {4E2417E7-FDC3-46D7-B976-84A97B500B74} = {707B4313-8EF8-4D0F-A95E-590783422187} - {EEFDA89D-7E11-7609-5383-FA1ADEA88CF4} = {707B4313-8EF8-4D0F-A95E-590783422187} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {7459323B-44F6-4E07-8574-E1B4B525086B} - EndGlobalSection - GlobalSection(TestCaseManagementSettings) = postSolution - CategoryFile = NTwain.vsmdi - EndGlobalSection -EndGlobal diff --git a/NTwain4.slnx b/NTwain4.slnx new file mode 100644 index 0000000..98ffbab --- /dev/null +++ b/NTwain4.slnx @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/README.md b/README.md index ce7b487..354230d 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ the TWAIN Working Group. V4 of this lib has these features: * Targets TWAIN version 2.5. -* Runs under supported framework (4.6.2+) and netcore variants (6.0+). +* Runs under supported framework (4.6.2+) and netcore variants (8.0+). * Easier to use than the low-level C API with many dotnet niceties. * Attempt at reducing heap allocations compared to previous versions. @@ -23,17 +23,8 @@ V4 of this lib has these features: These are not implemented yet in this early version: -* Image memory transfer (DAT_IMAGEMEMXFER). -* Audio native transfer (probably never will). - -As with previous versions, only Windows has been tested on and thus -supported really. Other changes include - * All TWAIN data types are now struct instead of class (and they come -from [twaincs](https://github.com/twain/twain-cs) for correctness. It may have -been easier to implement them as classes when starting out this lib, but -it's not really ideal anymore. The change also makes them match the twain.h -names and the spec pdf. +from [twaincs](https://github.com/twain/twain-cs) for correctness. * All lower-level TWAIN APIs are public instead of hidden away. diff --git a/csizes/WM_Constants.txt b/csizes/WM_Constants.txt new file mode 100644 index 0000000..81bbe4d --- /dev/null +++ b/csizes/WM_Constants.txt @@ -0,0 +1,372 @@ +Windows Message (WM_) Constants and Values +=========================================== +Comprehensive list of Windows Message constants from WinUser.h (Windows SDK) + +======================================== +BASIC WINDOW MESSAGES +======================================== +#define WM_NULL 0x0000 +#define WM_CREATE 0x0001 +#define WM_DESTROY 0x0002 +#define WM_MOVE 0x0003 +#define WM_SIZE 0x0005 +#define WM_ACTIVATE 0x0006 +#define WM_SETFOCUS 0x0007 +#define WM_KILLFOCUS 0x0008 +#define WM_ENABLE 0x000A +#define WM_SETREDRAW 0x000B +#define WM_SETTEXT 0x000C +#define WM_GETTEXT 0x000D +#define WM_GETTEXTLENGTH 0x000E +#define WM_PAINT 0x000F +#define WM_CLOSE 0x0010 +#define WM_QUERYENDSESSION 0x0011 +#define WM_QUIT 0x0012 +#define WM_QUERYOPEN 0x0013 +#define WM_ERASEBKGND 0x0014 +#define WM_SYSCOLORCHANGE 0x0015 +#define WM_ENDSESSION 0x0016 +#define WM_SHOWWINDOW 0x0018 +#define WM_WININICHANGE 0x001A +#define WM_SETTINGCHANGE 0x001A /* Same as WM_WININICHANGE */ +#define WM_DEVMODECHANGE 0x001B +#define WM_ACTIVATEAPP 0x001C +#define WM_FONTCHANGE 0x001D +#define WM_TIMECHANGE 0x001E +#define WM_CANCELMODE 0x001F +#define WM_SETCURSOR 0x0020 +#define WM_MOUSEACTIVATE 0x0021 +#define WM_CHILDACTIVATE 0x0022 +#define WM_QUEUESYNC 0x0023 +#define WM_GETMINMAXINFO 0x0024 +#define WM_PAINTICON 0x0026 +#define WM_ICONERASEBKGND 0x0027 +#define WM_NEXTDLGCTL 0x0028 +#define WM_SPOOLERSTATUS 0x002A +#define WM_DRAWITEM 0x002B +#define WM_MEASUREITEM 0x002C +#define WM_DELETEITEM 0x002D +#define WM_VKEYTOITEM 0x002E +#define WM_CHARTOITEM 0x002F +#define WM_SETFONT 0x0030 +#define WM_GETFONT 0x0031 +#define WM_SETHOTKEY 0x0032 +#define WM_GETHOTKEY 0x0033 +#define WM_QUERYDRAGICON 0x0037 +#define WM_COMPAREITEM 0x0039 +#define WM_GETOBJECT 0x003D +#define WM_COMPACTING 0x0041 +#define WM_COMMNOTIFY 0x0044 /* No longer supported */ +#define WM_WINDOWPOSCHANGING 0x0046 +#define WM_WINDOWPOSCHANGED 0x0047 +#define WM_POWER 0x0048 +#define WM_COPYDATA 0x004A +#define WM_CANCELJOURNAL 0x004B +#define WM_NOTIFY 0x004E +#define WM_INPUTLANGCHANGEREQUEST 0x0050 +#define WM_INPUTLANGCHANGE 0x0051 +#define WM_TCARD 0x0052 +#define WM_HELP 0x0053 +#define WM_USERCHANGED 0x0054 +#define WM_NOTIFYFORMAT 0x0055 + +======================================== +NONCLIENT MESSAGES +======================================== +#define WM_CONTEXTMENU 0x007B +#define WM_STYLECHANGING 0x007C +#define WM_STYLECHANGED 0x007D +#define WM_DISPLAYCHANGE 0x007E +#define WM_GETICON 0x007F +#define WM_SETICON 0x0080 +#define WM_NCCREATE 0x0081 +#define WM_NCDESTROY 0x0082 +#define WM_NCCALCSIZE 0x0083 +#define WM_NCHITTEST 0x0084 +#define WM_NCPAINT 0x0085 +#define WM_NCACTIVATE 0x0086 +#define WM_GETDLGCODE 0x0087 +#define WM_SYNCPAINT 0x0088 +#define WM_NCMOUSEMOVE 0x00A0 +#define WM_NCLBUTTONDOWN 0x00A1 +#define WM_NCLBUTTONUP 0x00A2 +#define WM_NCLBUTTONDBLCLK 0x00A3 +#define WM_NCRBUTTONDOWN 0x00A4 +#define WM_NCRBUTTONUP 0x00A5 +#define WM_NCRBUTTONDBLCLK 0x00A6 +#define WM_NCMBUTTONDOWN 0x00A7 +#define WM_NCMBUTTONUP 0x00A8 +#define WM_NCMBUTTONDBLCLK 0x00A9 +#define WM_NCXBUTTONDOWN 0x00AB +#define WM_NCXBUTTONUP 0x00AC +#define WM_NCXBUTTONDBLCLK 0x00AD + +======================================== +INPUT MESSAGES +======================================== +#define WM_INPUT_DEVICE_CHANGE 0x00FE +#define WM_INPUT 0x00FF + +======================================== +KEYBOARD MESSAGES +======================================== +#define WM_KEYFIRST 0x0100 +#define WM_KEYDOWN 0x0100 /* Same as WM_KEYFIRST */ +#define WM_KEYUP 0x0101 +#define WM_CHAR 0x0102 +#define WM_DEADCHAR 0x0103 +#define WM_SYSKEYDOWN 0x0104 +#define WM_SYSKEYUP 0x0105 +#define WM_SYSCHAR 0x0106 +#define WM_SYSDEADCHAR 0x0107 +#define WM_UNICHAR 0x0109 +#define WM_KEYLAST 0x0109 /* Same as WM_UNICHAR */ + +======================================== +IME MESSAGES +======================================== +#define WM_IME_STARTCOMPOSITION 0x010D +#define WM_IME_ENDCOMPOSITION 0x010E +#define WM_IME_COMPOSITION 0x010F +#define WM_IME_KEYLAST 0x010F + +======================================== +DIALOG & COMMAND MESSAGES +======================================== +#define WM_INITDIALOG 0x0110 +#define WM_COMMAND 0x0111 +#define WM_SYSCOMMAND 0x0112 +#define WM_TIMER 0x0113 +#define WM_HSCROLL 0x0114 +#define WM_VSCROLL 0x0115 +#define WM_INITMENU 0x0116 +#define WM_INITMENUPOPUP 0x0117 +#define WM_GESTURE 0x0119 +#define WM_GESTURENOTIFY 0x011A +#define WM_MENUSELECT 0x011F +#define WM_MENUCHAR 0x0120 +#define WM_ENTERIDLE 0x0121 +#define WM_MENURBUTTONUP 0x0122 +#define WM_MENUDRAG 0x0123 +#define WM_MENUGETOBJECT 0x0124 +#define WM_UNINITMENUPOPUP 0x0125 +#define WM_MENUCOMMAND 0x0126 +#define WM_CHANGEUISTATE 0x0127 +#define WM_UPDATEUISTATE 0x0128 +#define WM_QUERYUISTATE 0x0129 + +======================================== +CONTROL COLOR MESSAGES +======================================== +#define WM_CTLCOLORMSGBOX 0x0132 +#define WM_CTLCOLOREDIT 0x0133 +#define WM_CTLCOLORLISTBOX 0x0134 +#define WM_CTLCOLORBTN 0x0135 +#define WM_CTLCOLORDLG 0x0136 +#define WM_CTLCOLORSCROLLBAR 0x0137 +#define WM_CTLCOLORSTATIC 0x0138 + +======================================== +MENU MESSAGES +======================================== +#define MN_GETHMENU 0x01E1 + +======================================== +MOUSE MESSAGES +======================================== +#define WM_MOUSEFIRST 0x0200 +#define WM_MOUSEMOVE 0x0200 /* Same as WM_MOUSEFIRST */ +#define WM_LBUTTONDOWN 0x0201 +#define WM_LBUTTONUP 0x0202 +#define WM_LBUTTONDBLCLK 0x0203 +#define WM_RBUTTONDOWN 0x0204 +#define WM_RBUTTONUP 0x0205 +#define WM_RBUTTONDBLCLK 0x0206 +#define WM_MBUTTONDOWN 0x0207 +#define WM_MBUTTONUP 0x0208 +#define WM_MBUTTONDBLCLK 0x0209 +#define WM_MOUSEWHEEL 0x020A +#define WM_XBUTTONDOWN 0x020B +#define WM_XBUTTONUP 0x020C +#define WM_XBUTTONDBLCLK 0x020D +#define WM_MOUSEHWHEEL 0x020E +#define WM_MOUSELAST 0x020E /* Same as WM_MOUSEHWHEEL */ + +======================================== +PARENT NOTIFICATION & MENU LOOP +======================================== +#define WM_PARENTNOTIFY 0x0210 +#define WM_ENTERMENULOOP 0x0211 +#define WM_EXITMENULOOP 0x0212 +#define WM_NEXTMENU 0x0213 +#define WM_SIZING 0x0214 +#define WM_CAPTURECHANGED 0x0215 +#define WM_MOVING 0x0216 +#define WM_POWERBROADCAST 0x0218 +#define WM_DEVICECHANGE 0x0219 + +======================================== +MDI MESSAGES +======================================== +#define WM_MDICREATE 0x0220 +#define WM_MDIDESTROY 0x0221 +#define WM_MDIACTIVATE 0x0222 +#define WM_MDIRESTORE 0x0223 +#define WM_MDINEXT 0x0224 +#define WM_MDIMAXIMIZE 0x0225 +#define WM_MDITILE 0x0226 +#define WM_MDICASCADE 0x0227 +#define WM_MDIICONARRANGE 0x0228 +#define WM_MDIGETACTIVE 0x0229 +#define WM_MDISETMENU 0x0230 +#define WM_ENTERSIZEMOVE 0x0231 +#define WM_EXITSIZEMOVE 0x0232 +#define WM_DROPFILES 0x0233 +#define WM_MDIREFRESHMENU 0x0234 + +======================================== +TOUCH & POINTER MESSAGES +======================================== +#define WM_POINTERDEVICECHANGE 0x0238 +#define WM_POINTERDEVICEINRANGE 0x0239 +#define WM_POINTERDEVICEOUTOFRANGE 0x023A +#define WM_TOUCH 0x0240 +#define WM_NCPOINTERUPDATE 0x0241 +#define WM_NCPOINTERDOWN 0x0242 +#define WM_NCPOINTERUP 0x0243 +#define WM_POINTERUPDATE 0x0245 +#define WM_POINTERDOWN 0x0246 +#define WM_POINTERUP 0x0247 +#define WM_POINTERENTER 0x0249 +#define WM_POINTERLEAVE 0x024A +#define WM_POINTERACTIVATE 0x024B +#define WM_POINTERCAPTURECHANGED 0x024C +#define WM_TOUCHHITTESTING 0x024D +#define WM_POINTERWHEEL 0x024E +#define WM_POINTERHWHEEL 0x024F +#define DM_POINTERHITTEST 0x0250 +#define WM_POINTERROUTEDTO 0x0251 +#define WM_POINTERROUTEDAWAY 0x0252 +#define WM_POINTERROUTEDRELEASED 0x0253 + +======================================== +IME MESSAGES (EXTENDED) +======================================== +#define WM_IME_SETCONTEXT 0x0281 +#define WM_IME_NOTIFY 0x0282 +#define WM_IME_CONTROL 0x0283 +#define WM_IME_COMPOSITIONFULL 0x0284 +#define WM_IME_SELECT 0x0285 +#define WM_IME_CHAR 0x0286 +#define WM_IME_REQUEST 0x0288 +#define WM_IME_KEYDOWN 0x0290 +#define WM_IME_KEYUP 0x0291 + +======================================== +MOUSE HOVER/LEAVE MESSAGES +======================================== +#define WM_NCMOUSEHOVER 0x02A0 +#define WM_MOUSEHOVER 0x02A1 +#define WM_NCMOUSELEAVE 0x02A2 +#define WM_MOUSELEAVE 0x02A3 + +======================================== +TERMINAL SERVICES +======================================== +#define WM_WTSSESSION_CHANGE 0x02B1 + +======================================== +TABLET MESSAGES +======================================== +#define WM_TABLET_FIRST 0x02C0 +#define WM_TABLET_LAST 0x02DF + +======================================== +DPI MESSAGES +======================================== +#define WM_DPICHANGED 0x02E0 +#define WM_DPICHANGED_BEFOREPARENT 0x02E2 +#define WM_DPICHANGED_AFTERPARENT 0x02E3 +#define WM_GETDPISCALEDSIZE 0x02E4 + +======================================== +CLIPBOARD MESSAGES +======================================== +#define WM_CUT 0x0300 +#define WM_COPY 0x0301 +#define WM_PASTE 0x0302 +#define WM_CLEAR 0x0303 +#define WM_UNDO 0x0304 +#define WM_RENDERFORMAT 0x0305 +#define WM_RENDERALLFORMATS 0x0306 +#define WM_DESTROYCLIPBOARD 0x0307 +#define WM_DRAWCLIPBOARD 0x0308 +#define WM_PAINTCLIPBOARD 0x0309 +#define WM_VSCROLLCLIPBOARD 0x030A +#define WM_SIZECLIPBOARD 0x030B +#define WM_ASKCBFORMATNAME 0x030C +#define WM_CHANGECBCHAIN 0x030D +#define WM_HSCROLLCLIPBOARD 0x030E +#define WM_QUERYNEWPALETTE 0x030F +#define WM_PALETTEISCHANGING 0x0310 +#define WM_PALETTECHANGED 0x0311 +#define WM_HOTKEY 0x0312 +#define WM_PRINT 0x0317 +#define WM_PRINTCLIENT 0x0318 +#define WM_APPCOMMAND 0x0319 +#define WM_THEMECHANGED 0x031A +#define WM_CLIPBOARDUPDATE 0x031D + +======================================== +DWM (DESKTOP WINDOW MANAGER) MESSAGES +======================================== +#define WM_DWMCOMPOSITIONCHANGED 0x031E +#define WM_DWMNCRENDERINGCHANGED 0x031F +#define WM_DWMCOLORIZATIONCOLORCHANGED 0x0320 +#define WM_DWMWINDOWMAXIMIZEDCHANGE 0x0321 +#define WM_DWMSENDICONICTHUMBNAIL 0x0323 +#define WM_DWMSENDICONICLIVEPREVIEWBITMAP 0x0326 + +======================================== +MISCELLANEOUS MESSAGES +======================================== +#define WM_GETTITLEBARINFOEX 0x033F + +======================================== +HANDHELD/DEVICE MESSAGES +======================================== +#define WM_HANDHELDFIRST 0x0358 +#define WM_HANDHELDLAST 0x035F + +======================================== +APPLICATION FRAMEWORK MESSAGES +======================================== +#define WM_AFXFIRST 0x0360 +#define WM_AFXLAST 0x037F + +======================================== +PEN WINDOWS MESSAGES +======================================== +#define WM_PENWINFIRST 0x0380 +#define WM_PENWINLAST 0x038F + +======================================== +USER-DEFINED MESSAGES +======================================== +#define WM_APP 0x8000 +#define WM_USER 0x0400 + +==================================================== +NOTES: +==================================================== +- WM_SETTINGCHANGE is an alias for WM_WININICHANGE (0x001A) +- WM_KEYFIRST and WM_KEYDOWN both have the value 0x0100 +- WM_KEYLAST and WM_UNICHAR both have the value 0x0109 +- WM_MOUSEFIRST and WM_MOUSEMOVE both have the value 0x0200 +- WM_MOUSELAST and WM_MOUSEHWHEEL both have the value 0x020E +- Values are in hexadecimal format +- WM_USER (0x0400) through 0x7FFF: Integer messages for use by private window classes +- WM_APP (0x8000) through 0xBFFF: Messages available for use by applications +- 0xC000 through 0xFFFF: String messages for use by applications (RegisterWindowMessage) +- Generated from WinUser.h (Windows SDK) +==================================================== diff --git a/samples/ConsoleSample/ConsoleSample.csproj b/samples/ConsoleSample/ConsoleSample.csproj new file mode 100644 index 0000000..7202b70 --- /dev/null +++ b/samples/ConsoleSample/ConsoleSample.csproj @@ -0,0 +1,20 @@ + + + + Exe + net10.0 + enable + enable + x86;x64 + app.manifest + + + + + + + + + + + diff --git a/samples/ConsoleSample/Program.cs b/samples/ConsoleSample/Program.cs new file mode 100644 index 0000000..ba5e6b1 --- /dev/null +++ b/samples/ConsoleSample/Program.cs @@ -0,0 +1,146 @@ +using NTwain; +using NTwain.Data; +using NTwain.Events; +using System.Diagnostics; + +namespace ConsoleSample; + +internal class Program +{ + static void Main(string[] args) + { + Console.WriteLine($"[{(Environment.Is64BitProcess ? "64bit" : "32bit")}] Creating TwainAppSession instance..."); + + bool sourceDisabledEventFired = false; + + using var twain = new NTwain.TwainAppSession(); + twain.SourceDisabled += (s, e) => + { + sourceDisabledEventFired = true; + Console.WriteLine($"Source disabled: {e.ProductName}"); + }; + twain.Transferred += OnTransferred; + + Console.WriteLine("Opening DSM..."); + var sts = twain.OpenDsm(); + Console.WriteLine($"OpenDsm returned: {sts}"); + + if (sts.IsSuccess) + { + while (true) + { + var sources = twain.GetSources(); + Console.WriteLine($"Found {sources.Count} sources."); + Console.WriteLine(" Source 0: [Choose by old dialog]"); + for (var i = 0; i < sources.Count; i++) + { + var src = sources[i]; + Console.WriteLine($" Source {i + 1}: {src.ProductName}"); + } + + Console.WriteLine("Choose a source index to open (or just press Enter to skip): "); + var input = Console.ReadLine(); + TWIdentityWrapper? selectedSource = null; + var validInput = int.TryParse(input, out int index); + if (validInput && index > 0 && index <= sources.Count) + { + selectedSource = sources[index - 1]; + } + else if (validInput && index == 0) + { + Console.WriteLine("Showing user select dialog..."); + sts = twain.ShowUserSelect(); + Console.WriteLine($"OpenSource returned: {sts}"); + + if (sts.IsSuccess) + { + selectedSource = twain.DefaultSource; + } + } + + if (selectedSource == null) + { + break; + } + + + Console.WriteLine($"Opening source: {selectedSource.ProductName}"); + sts = twain.OpenSource(selectedSource); + Console.WriteLine($"OpenSource returned: {sts}"); + + if (sts.IsSuccess) + { + sourceDisabledEventFired = false; + xferCount = 0; + watch.Restart(); + if (twain.EnableSource(NTwain.SourceEnableOption.ShowUI).IsSuccess) + { + while(!sourceDisabledEventFired) + { + Thread.Sleep(500); + } + } + else + { + Console.WriteLine("Failed to enable source."); + } + + + Console.WriteLine($"Closing source: {selectedSource.ProductName}"); + sts = twain.CloseSource(); + Console.WriteLine($"CloseSource returned: {sts}"); + } + } + + Thread.Sleep(1000); + + Console.WriteLine("Closing DSM..."); + sts = twain.CloseDsm(); + Console.WriteLine($"CloseDsm returned: {sts}"); + } + + + Console.WriteLine("Press Enter to quit..."); + Console.ReadLine(); + } + + static int xferCount = 0; + static Stopwatch watch = new Stopwatch(); + private static void OnTransferred(TwainAppSession sender, TransferredEventArgs e) + { + if (e.Data != null) + { + var saveFile = Path.Combine(Environment.CurrentDirectory, $"twain_{DateTime.Now:yyyyMMdd_HHmmss}_{xferCount}"); + + using (var img = new ImageMagick.MagickImage(e.Data.AsStream())) + { + var format = ImageMagick.MagickFormat.Png; + if (img.ColorType == ImageMagick.ColorType.Palette) + { + // bw or gray + saveFile += ".png"; + } + else + { + // color + saveFile += ".jpg"; + format = ImageMagick.MagickFormat.Jpeg; + img.Settings.Compression = ImageMagick.CompressionMethod.JPEG; + img.Quality = (uint)85; + } + img.Write(saveFile, format); + Console.WriteLine($"SUCCESS! Got twain memory data #{++xferCount} on thread {Environment.CurrentManagedThreadId}, saving to {saveFile}."); + } + } + else if (e.FileInfo != null) + { + var fi = e.FileInfo.Value; + Console.WriteLine($"SUCCESS! Got twain file data #{++xferCount} on thread {Environment.CurrentManagedThreadId} as {fi.FileName}."); + } + else + { + Console.WriteLine($"BUMMER! No twain data #{++xferCount} on thread {Environment.CurrentManagedThreadId}."); + } + e.Dispose(); + } +} diff --git a/samples/ConsoleSample/app.manifest b/samples/ConsoleSample/app.manifest new file mode 100644 index 0000000..b42362a --- /dev/null +++ b/samples/ConsoleSample/app.manifest @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + true + PerMonitorV2 + true + UTF-8 + SegmentHeap + + + + + + + + + + + diff --git a/samples/ScannerTester/ScannerTester.csproj b/samples/KodakTester/KodakTester.csproj similarity index 89% rename from samples/ScannerTester/ScannerTester.csproj rename to samples/KodakTester/KodakTester.csproj index 66b5c42..6dd355a 100644 --- a/samples/ScannerTester/ScannerTester.csproj +++ b/samples/KodakTester/KodakTester.csproj @@ -2,7 +2,7 @@ WinExe - net10.0-windows7.0 + net10.0-windows enable true enable diff --git a/samples/ScannerTester/MainForm.Designer.cs b/samples/KodakTester/MainForm.Designer.cs similarity index 71% rename from samples/ScannerTester/MainForm.Designer.cs rename to samples/KodakTester/MainForm.Designer.cs index 3cb6c3b..4d23482 100644 --- a/samples/ScannerTester/MainForm.Designer.cs +++ b/samples/KodakTester/MainForm.Designer.cs @@ -1,4 +1,4 @@ -namespace ScannerTester +namespace KodakTester { partial class MainForm { @@ -59,17 +59,19 @@ // label1 // label1.AutoSize = true; - label1.Location = new Point(12, 9); + label1.Location = new Point(10, 7); + label1.Margin = new Padding(2, 0, 2, 0); label1.Name = "label1"; - label1.Size = new Size(612, 25); + label1.Size = new Size(418, 20); label1.TabIndex = 0; - label1.Text = "Use this tool to see if the scanner can be used with the ScanCloud Scan App"; + label1.Text = "Use this tool to test special features with Kodak ixxxx scanners"; // // btnSelectScanner // - btnSelectScanner.Location = new Point(12, 46); + btnSelectScanner.Location = new Point(10, 37); + btnSelectScanner.Margin = new Padding(2, 2, 2, 2); btnSelectScanner.Name = "btnSelectScanner"; - btnSelectScanner.Size = new Size(238, 34); + btnSelectScanner.Size = new Size(190, 27); btnSelectScanner.TabIndex = 1; btnSelectScanner.Text = "Choose Scanner..."; btnSelectScanner.UseVisualStyleBackColor = true; @@ -90,9 +92,11 @@ groupSettings.Controls.Add(label4); groupSettings.Controls.Add(listDpi); groupSettings.Controls.Add(label3); - groupSettings.Location = new Point(12, 99); + groupSettings.Location = new Point(10, 79); + groupSettings.Margin = new Padding(2, 2, 2, 2); groupSettings.Name = "groupSettings"; - groupSettings.Size = new Size(742, 932); + groupSettings.Padding = new Padding(2, 2, 2, 2); + groupSettings.Size = new Size(594, 746); groupSettings.TabIndex = 2; groupSettings.TabStop = false; groupSettings.Text = "Settings"; @@ -101,42 +105,47 @@ // listFormat.DropDownStyle = ComboBoxStyle.DropDownList; listFormat.FormattingEnabled = true; - listFormat.Location = new Point(157, 243); + listFormat.Location = new Point(126, 194); + listFormat.Margin = new Padding(2, 2, 2, 2); listFormat.Name = "listFormat"; - listFormat.Size = new Size(182, 33); + listFormat.Size = new Size(146, 28); listFormat.TabIndex = 10; // // label7 // label7.AutoSize = true; - label7.Location = new Point(47, 246); + label7.Location = new Point(38, 197); + label7.Margin = new Padding(2, 0, 2, 0); label7.Name = "label7"; - label7.Size = new Size(100, 25); + label7.Size = new Size(83, 20); label7.TabIndex = 9; label7.Text = "File Format"; // // boxNamePrefix // - boxNamePrefix.Location = new Point(157, 207); + boxNamePrefix.Location = new Point(126, 166); + boxNamePrefix.Margin = new Padding(2, 2, 2, 2); boxNamePrefix.Name = "boxNamePrefix"; - boxNamePrefix.Size = new Size(182, 31); + boxNamePrefix.Size = new Size(146, 27); boxNamePrefix.TabIndex = 8; boxNamePrefix.Text = "Capture_"; // // label6 // label6.AutoSize = true; - label6.Location = new Point(13, 210); + label6.Location = new Point(10, 168); + label6.Margin = new Padding(2, 0, 2, 0); label6.Name = "label6"; - label6.Size = new Size(138, 25); + label6.Size = new Size(117, 20); label6.TabIndex = 7; label6.Text = "File Name Prefix"; // // btnOpenFolder // - btnOpenFolder.Location = new Point(275, 167); + btnOpenFolder.Location = new Point(220, 134); + btnOpenFolder.Margin = new Padding(2, 2, 2, 2); btnOpenFolder.Name = "btnOpenFolder"; - btnOpenFolder.Size = new Size(112, 34); + btnOpenFolder.Size = new Size(90, 27); btnOpenFolder.TabIndex = 6; btnOpenFolder.Text = "Open"; btnOpenFolder.UseVisualStyleBackColor = true; @@ -144,9 +153,10 @@ // // btnBrowseFolder // - btnBrowseFolder.Location = new Point(157, 167); + btnBrowseFolder.Location = new Point(126, 134); + btnBrowseFolder.Margin = new Padding(2, 2, 2, 2); btnBrowseFolder.Name = "btnBrowseFolder"; - btnBrowseFolder.Size = new Size(112, 34); + btnBrowseFolder.Size = new Size(90, 27); btnBrowseFolder.TabIndex = 6; btnBrowseFolder.Text = "Browse..."; btnBrowseFolder.UseVisualStyleBackColor = true; @@ -155,36 +165,40 @@ // boxFolder // boxFolder.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; - boxFolder.Location = new Point(157, 130); + boxFolder.Location = new Point(126, 104); + boxFolder.Margin = new Padding(2, 2, 2, 2); boxFolder.Name = "boxFolder"; - boxFolder.Size = new Size(556, 31); + boxFolder.Size = new Size(446, 27); boxFolder.TabIndex = 5; boxFolder.Text = "Images"; // // label5 // label5.AutoSize = true; - label5.Location = new Point(47, 133); + label5.Location = new Point(38, 106); + label5.Margin = new Padding(2, 0, 2, 0); label5.Name = "label5"; - label5.Size = new Size(104, 25); + label5.Size = new Size(86, 20); label5.TabIndex = 4; label5.Text = "Save Folder"; // // boxLimit // - boxLimit.Location = new Point(157, 93); + boxLimit.Location = new Point(126, 74); + boxLimit.Margin = new Padding(2, 2, 2, 2); boxLimit.Minimum = new decimal(new int[] { 1, 0, 0, int.MinValue }); boxLimit.Name = "boxLimit"; - boxLimit.Size = new Size(182, 31); + boxLimit.Size = new Size(146, 27); boxLimit.TabIndex = 3; boxLimit.Value = new decimal(new int[] { 1, 0, 0, int.MinValue }); // // label4 // label4.AutoSize = true; - label4.Location = new Point(35, 95); + label4.Location = new Point(28, 76); + label4.Margin = new Padding(2, 0, 2, 0); label4.Name = "label4"; - label4.Size = new Size(116, 25); + label4.Size = new Size(98, 20); label4.TabIndex = 2; label4.Text = "Transfer Limit"; // @@ -192,26 +206,29 @@ // listDpi.DropDownStyle = ComboBoxStyle.DropDownList; listDpi.FormattingEnabled = true; - listDpi.Location = new Point(157, 54); + listDpi.Location = new Point(126, 43); + listDpi.Margin = new Padding(2, 2, 2, 2); listDpi.Name = "listDpi"; - listDpi.Size = new Size(182, 33); + listDpi.Size = new Size(146, 28); listDpi.TabIndex = 1; // // label3 // label3.AutoSize = true; - label3.Location = new Point(111, 57); + label3.Location = new Point(89, 46); + label3.Margin = new Padding(2, 0, 2, 0); label3.Name = "label3"; - label3.Size = new Size(40, 25); + label3.Size = new Size(32, 20); label3.TabIndex = 0; label3.Text = "DPI"; // // lblCurScanner // lblCurScanner.AutoSize = true; - lblCurScanner.Location = new Point(256, 51); + lblCurScanner.Location = new Point(205, 41); + lblCurScanner.Margin = new Padding(2, 0, 2, 0); lblCurScanner.Name = "lblCurScanner"; - lblCurScanner.Size = new Size(124, 25); + lblCurScanner.Size = new Size(104, 20); lblCurScanner.TabIndex = 3; lblCurScanner.Text = "None selected"; // @@ -224,9 +241,11 @@ groupTest.Controls.Add(btnStop); groupTest.Controls.Add(btnTransfer); groupTest.Controls.Add(btnDriverOnly); - groupTest.Location = new Point(760, 99); + groupTest.Location = new Point(608, 79); + groupTest.Margin = new Padding(2, 2, 2, 2); groupTest.Name = "groupTest"; - groupTest.Size = new Size(1038, 932); + groupTest.Padding = new Padding(2, 2, 2, 2); + groupTest.Size = new Size(830, 746); groupTest.TabIndex = 4; groupTest.TabStop = false; groupTest.Text = "Test"; @@ -234,27 +253,30 @@ // boxLog // boxLog.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; - boxLog.Location = new Point(22, 118); + boxLog.Location = new Point(18, 94); + boxLog.Margin = new Padding(2, 2, 2, 2); boxLog.Name = "boxLog"; - boxLog.Size = new Size(999, 796); + boxLog.Size = new Size(800, 638); boxLog.TabIndex = 4; boxLog.Text = ""; // // label2 // label2.AutoSize = true; - label2.Location = new Point(22, 90); + label2.Location = new Point(18, 72); + label2.Margin = new Padding(2, 0, 2, 0); label2.Name = "label2"; - label2.Size = new Size(50, 25); + label2.Size = new Size(40, 20); label2.TabIndex = 3; label2.Text = "Logs"; // // ckShowUI // ckShowUI.AutoSize = true; - ckShowUI.Location = new Point(451, 43); + ckShowUI.Location = new Point(361, 34); + ckShowUI.Margin = new Padding(2, 2, 2, 2); ckShowUI.Name = "ckShowUI"; - ckShowUI.Size = new Size(253, 29); + ckShowUI.Size = new Size(210, 24); ckShowUI.TabIndex = 2; ckShowUI.Text = "Show driver during capture"; ckShowUI.UseVisualStyleBackColor = true; @@ -262,9 +284,10 @@ // btnStop // btnStop.Anchor = AnchorStyles.Top | AnchorStyles.Right; - btnStop.Location = new Point(897, 39); + btnStop.Location = new Point(718, 31); + btnStop.Margin = new Padding(2, 2, 2, 2); btnStop.Name = "btnStop"; - btnStop.Size = new Size(124, 34); + btnStop.Size = new Size(99, 27); btnStop.TabIndex = 2; btnStop.Text = "Stop"; btnStop.UseVisualStyleBackColor = true; @@ -272,9 +295,10 @@ // // btnTransfer // - btnTransfer.Location = new Point(239, 39); + btnTransfer.Location = new Point(191, 31); + btnTransfer.Margin = new Padding(2, 2, 2, 2); btnTransfer.Name = "btnTransfer"; - btnTransfer.Size = new Size(206, 34); + btnTransfer.Size = new Size(165, 27); btnTransfer.TabIndex = 1; btnTransfer.Text = "Start Capture"; btnTransfer.UseVisualStyleBackColor = true; @@ -282,9 +306,10 @@ // // btnDriverOnly // - btnDriverOnly.Location = new Point(22, 39); + btnDriverOnly.Location = new Point(18, 31); + btnDriverOnly.Margin = new Padding(2, 2, 2, 2); btnDriverOnly.Name = "btnDriverOnly"; - btnDriverOnly.Size = new Size(206, 34); + btnDriverOnly.Size = new Size(165, 27); btnDriverOnly.TabIndex = 0; btnDriverOnly.Text = "Open Driver UI"; btnDriverOnly.UseVisualStyleBackColor = true; @@ -292,17 +317,18 @@ // // MainForm // - AutoScaleDimensions = new SizeF(10F, 25F); + AutoScaleDimensions = new SizeF(8F, 20F); AutoScaleMode = AutoScaleMode.Font; - ClientSize = new Size(1810, 1043); + ClientSize = new Size(1448, 834); Controls.Add(groupTest); Controls.Add(lblCurScanner); Controls.Add(groupSettings); Controls.Add(btnSelectScanner); Controls.Add(label1); + Margin = new Padding(2, 2, 2, 2); Name = "MainForm"; SizeGripStyle = SizeGripStyle.Show; - Text = "Scanner Tester Utility"; + Text = "Kodak Tester Utility"; groupSettings.ResumeLayout(false); groupSettings.PerformLayout(); ((System.ComponentModel.ISupportInitialize)boxLimit).EndInit(); diff --git a/samples/KodakTester/MainForm.cs b/samples/KodakTester/MainForm.cs new file mode 100644 index 0000000..0df0413 --- /dev/null +++ b/samples/KodakTester/MainForm.cs @@ -0,0 +1,586 @@ +using NTwain; +using NTwain.Data; +using NTwain.Data.Kds; +using NTwain.Events; +using NTwain.Triplets; +using System.Diagnostics; +using System.Text; + +namespace KodakTester; + +public partial class MainForm : Form +{ + TwainAppSession _twain; + private bool _stopTransfer; + + public MainForm() + { + InitializeComponent(); + + _twain = new TwainAppSession(appThreadContext: SynchronizationContext.Current); + _twain.TransferReady += _twain_TransferReady; + _twain.Transferred += _twain_Transferred; + _twain.SourceDisabled += _twain_SourceDisabled; + } + + private void _twain_SourceDisabled(TwainAppSession sender, TWIdentityWrapper e) + { + + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + _twain.OpenDsm(); + //_ = _twain.OpenDSMAsync(); + } + + protected override void OnFormClosed(FormClosedEventArgs e) + { + _twain.CloseDsm(); + //_ = _twain.CloseDSMAsync(); + base.OnFormClosed(e); + } + + private void _twain_Transferred(TwainAppSession sender, TransferredEventArgs e) + { + TW_EXTIMAGEINFO extInfo = TW_EXTIMAGEINFO.CreateRequest(TWEI.CAMERA); + e.GetExtendedImageInfo(ref extInfo); + string? camera = null; + foreach (var ei in extInfo.AsInfos()) + { + if (ei.ReturnCode == TWRC.SUCCESS) + { + switch (ei.InfoId) + { + //case (TWEI)KDS_TWEI.HDR_PAGENUMBER: + // LogIt($"TWEI_HDR_PAGENUMBER Value = {ei.ReadNonPointerData()}"); + // break; + case TWEI.CAMERA: + camera = ei.ReadHandleString(_twain.MemoryManager); + LogIt($"{ei.InfoId} Value = {camera}"); + break; + } + } + else + { + LogIt($"{ei.InfoId} RC = {ei.ReturnCode}"); + } + } + extInfo.Free(_twain.MemoryManager); + + if (e.Data != null) + { + LogIt($"Received {e.ImageInfo.PixelType} in {e.ImageInfo.Compression} compressed memory image."); + var folder = boxFolder.Text; + if (string.IsNullOrWhiteSpace(folder)) + { + folder = "Images"; + Directory.CreateDirectory(folder); + boxFolder.Text = folder; + } + var prefix = boxNamePrefix.Text; + if (string.IsNullOrWhiteSpace(prefix)) + { + prefix = "Capture_"; + boxNamePrefix.Text = prefix; + } + + using (var img = System.Drawing.Image.FromStream(e.Data.AsStream())) + { + //var saveFile = img.SaveToSmallestFormat(folder, prefix, lossless: false).ToString(); + //LogIt($"File saved to {saveFile}"); + } + } + else if (e.FileInfo != null) + { + var info = e.FileInfo.Value; + var path = info.FileName.ToString(); + LogIt($"Received {e.ImageInfo.PixelType} {info.Format} in {e.ImageInfo.Compression} compressed file {path}"); + } + e.Dispose(); + LogIt(""); + } + + int _xferCount = 0; + private void _twain_TransferReady(TwainAppSession sender, TransferReadyEventArgs e) + { + if (_stopTransfer) + { + e.Cancel = CancelType.EndNow; + return; + } + + _xferCount++; + LogIt($"Got pending transfer with mode = {e.ImgXferMech}"); + if (e.ImgXferMech == TWSX.FILE) + { + var folder = boxFolder.Text; + if (string.IsNullOrWhiteSpace(folder)) + { + folder = "Images"; + Directory.CreateDirectory(folder); + boxFolder.Text = folder; + } + var prefix = boxNamePrefix.Text; + if (string.IsNullOrWhiteSpace(prefix)) + { + prefix = "Capture_"; + boxNamePrefix.Text = prefix; + } + + TWCP comp = TWCP.NONE; + TW_EXTIMAGEINFO extInfo = TW_EXTIMAGEINFO.CreateRequest((TWEI)KDS_TWEI.HDR_COMPRESSION); + e.GetExtendedImageInfo(ref extInfo); + foreach (var ei in extInfo.AsInfos()) + { + if (ei.ReturnCode == TWRC.SUCCESS) + { + switch (ei.InfoId) + { + case (TWEI)KDS_TWEI.HDR_COMPRESSION: + comp = ei.ReadNonPointerData(); + LogIt($"{ei.InfoId} Value = {comp}"); + break; + } + } + else + { + LogIt($"{ei.InfoId} RC = {ei.ReturnCode}"); + } + } + extInfo.Free(_twain.MemoryManager); + + LogIt($"Compression at ready step = {comp}"); + string? targetName = $"{prefix}_{_xferCount:D4}"; + TWFF format = TWFF.TIFF; + switch (comp) + { + case TWCP.JPEG: + targetName = $"{prefix}_{_xferCount:D4}.jpg"; + format = TWFF.JFIF; + break; + case TWCP.NONE: + targetName = $"{prefix}_{_xferCount:D4}.bmp"; + format = TWFF.BMP; + break; + case TWCP.GROUP4: + default: + targetName = $"{prefix}_{_xferCount:D4}.tif"; + break; + } + TW_SETUPFILEXFER setup = new() + { + FileName = Path.Combine(folder, targetName), + Format = format + }; + + var sts = e.SetupFileTransfer(ref setup); + + LogIt($"Want to save image as {setup.Format} {setup.FileName}.", sts); + + // verify it again + var appId = _twain.AppIdentity; + var srcId = _twain.CurrentSource!; + + sts = _twain.WrapInSTS(DGControl.SetupFileXfer.Get(appId, srcId, out setup)); + + LogIt($"Checked actual file settings as {setup.Format} {setup.FileName}.", sts); + + } + LogIt(""); + } + + protected override void OnFormClosing(FormClosingEventArgs e) + { + if (_twain.State > STATE.S5) + { + e.Cancel = true; + } + _twain.TryStepdown(STATE.S2); + base.OnFormClosing(e); + } + + private void btnSelectScanner_Click(object sender, EventArgs e) + { + var sts = _twain.ShowUserSelect(); + if (sts.IsSuccess && _twain.DefaultSource.Id > 0) + { + if (_twain.State > STATE.S3) + { + _twain.TryStepdown(STATE.S3); + } + sts = _twain.OpenSource(_twain.DefaultSource); + LogIt("Open scanner", sts); + if (sts.IsSuccess) + { + var src = _twain.CurrentSource; + lblCurScanner.Text = $"{src.ProductName} | v{src.Version} | protocol: {src.ProtocolMajor}.{src.ProtocolMinor}"; + LoadSettings(); + return; + } + } + + lblCurScanner.Text = "None selected"; + } + + private void LogIt(string msg) + { + boxLog.AppendText($"{msg}\n"); + } + private void LogIt(string msg, STS sts) + { + if (sts.IsSuccess) + { + boxLog.AppendText($"{msg} result = {sts.RC}\n"); + } + else + { + boxLog.AppendText($"{msg} result = {sts.RC} - {sts.ConditionCode}\n"); + } + } + + private void LoadSettings() + { + var mechs = _twain.Caps.ICAP_XFERMECH.Get().GetValues(); + + if (!mechs.Contains(TWSX.FILE)) + { + LogIt("File transfer is not supported."); + } + + var sts = _twain.Caps.ICAP_XFERMECH.Set(TWSX.FILE); + LogIt("Use file transfer", sts); + + if (_twain.Caps.ICAP_UNITS.GetCurrent().FirstOrDefault() != TWUN.INCHES) + { + sts = _twain.Caps.ICAP_UNITS.Set(TWUN.INCHES); + LogIt("Set unit to inches", sts); + } + + var dpis = _twain.Caps.ICAP_XRESOLUTION.Get().GetValues(); + listDpi.Items.Clear(); + if (dpis.Contains(200)) + { + listDpi.Items.Add(200); + listDpi.SelectedItem = 200; + } + else + { + LogIt("200 DPI doesn't appear to be supported."); + } + if (dpis.Contains(300)) + { + listDpi.Items.Add(300); + listDpi.SelectedItem = 300; + } + else + { + LogIt("300 DPI doesn't appear to be supported."); + } + + var formats = _twain.Caps.ICAP_IMAGEFILEFORMAT.Get().GetValues(); + listFormat.Items.Clear(); + foreach (var format in formats) + { + listFormat.Items.Add(format); + } + listFormat.SelectedItem = _twain.Caps.ICAP_IMAGEFILEFORMAT.GetCurrent().FirstOrDefault(); + + LogIt(""); + } + + private void btnDriverOnly_Click(object sender, EventArgs e) + { + if (_twain.State != STATE.S4) return; + + var sts = _twain.EnableSource(SourceEnableOption.UIOnly); + LogIt("Show drivers", sts); + LogIt(""); + } + + private void btnTransfer_Click(object sender, EventArgs e) + { + if (_twain.State != STATE.S4 || !EnsureBoxFolder()) return; + + + var _isIndustrialKodak = _twain.CurrentSource!.ProductName.ToString().StartsWith("KODAK Scanner: i"); + + if (_isIndustrialKodak) + { + CaptureAsKodakSDMI(); + } + else + { + CaptureAsStandardScanner(); + } + + _stopTransfer = false; + _xferCount = 0; + var sts = _twain.EnableSource(ckShowUI.Checked ? SourceEnableOption.ShowUI : SourceEnableOption.NoUI); + LogIt("Start capture", sts); + LogIt(""); + } + + private void CaptureAsKodakSDMI() + { + LogIt("Attempting Kodak SDMI mode"); + + LogIt($"Resolution supports {FlattenFlag(_twain.Caps.ICAP_XRESOLUTION.Supports)}"); + LogIt($"File format supports {FlattenFlag(_twain.Caps.ICAP_IMAGEFILEFORMAT.Supports)}"); + LogIt($"Compression supports {FlattenFlag(_twain.Caps.ICAP_COMPRESSION.Supports)}"); + LogIt($"EXTINFO supports {FlattenFlag(_twain.Caps.ICAP_EXTIMAGEINFO.Supports)}"); + + LogIt(""); + + var limit = (short)boxLimit.Value; + if (limit > 0) limit *= 2; + var sts = _twain.Caps.CAP_XFERCOUNT.Set(limit); + LogIt($"Set transfer limit {limit}", sts); + + sts = _twain.Caps.ICAP_EXTIMAGEINFO.Set(TW_BOOL.True); + LogIt($"Set extimageinfo enabled", sts); + + var format = (TWFF)listFormat.SelectedItem!; + sts = _twain.Caps.ICAP_IMAGEFILEFORMAT.Set(format); + LogIt($"Set {format} format.", sts); + + if (!sts.IsSuccess) + { + return; + } + + LogIt(""); + + var appId = _twain.AppIdentity; + var srcId = _twain.CurrentSource!; + + + TW_FILESYSTEM fs = new() { InputName = "/Camera_Bitonal_Both" }; + sts = _twain.WrapInSTS(DGControl.FileSystem.ChangeDirectory(appId, srcId, ref fs)); + LogIt("Change to bw cameras", sts); + if (sts.IsSuccess) + { + sts = _twain.Caps.CAP_CAMERAENABLED.Set(TW_BOOL.True); + LogIt("Set camera enabled", sts); + + var dpi = listDpi.SelectedValue == null ? 300 : Convert.ToInt32(listDpi.SelectedValue); + sts = _twain.Caps.ICAP_XRESOLUTION.Set(dpi); + LogIt("Set x-resolution", sts); + sts = _twain.Caps.ICAP_YRESOLUTION.Set(dpi); + LogIt("Set y-resolution", sts); + + + if (format != TWFF.BMP) + { + LogIt($"Current format={_twain.Caps.ICAP_IMAGEFILEFORMAT.GetCurrent().First()}"); + LogIt($"Current compression={_twain.Caps.ICAP_COMPRESSION.GetCurrent().First()}"); + if (_twain.Caps.ICAP_COMPRESSION.Supports.HasFlag(TWQC.SET)) + { + sts = _twain.Caps.ICAP_COMPRESSION.Set(TWCP.GROUP4); + LogIt("Set compression to group4", sts); + } + } + } + LogIt(""); + + + fs = new() { FileType = (int)TWFY.CAMERA, InputName = "/Camera_Color_Both" }; + sts = _twain.WrapInSTS(DGControl.FileSystem.ChangeDirectory(appId, srcId, ref fs)); + LogIt("Change to color cameras", sts); + if (sts.IsSuccess) + { + sts = _twain.Caps.CAP_CAMERAENABLED.Set(TW_BOOL.True); + LogIt("Set camera enabled", sts); + + + var dpi = listDpi.SelectedValue == null ? 300 : Convert.ToInt32(listDpi.SelectedValue); + sts = _twain.Caps.ICAP_XRESOLUTION.Set(dpi); + LogIt("Set x-resolution", sts); + sts = _twain.Caps.ICAP_YRESOLUTION.Set(dpi); + LogIt("Set y-resolution", sts); + + + if (format != TWFF.BMP) + { + LogIt($"Current format={_twain.Caps.ICAP_IMAGEFILEFORMAT.GetCurrent().First()}"); + LogIt($"Current compression={_twain.Caps.ICAP_COMPRESSION.GetCurrent().First()}"); + if (_twain.Caps.ICAP_COMPRESSION.Supports.HasFlag(TWQC.SET)) + { + sts = _twain.Caps.ICAP_COMPRESSION.Set(TWCP.JPEG); + LogIt("Set compression to jpg", sts); + if (sts.IsSuccess) + { + LogIt($"jpeg quality supports {FlattenFlag(_twain.Caps.ICAP_JPEGQUALITY.Supports)}"); + + short quality = 90; + sts = _twain.Caps.ICAP_JPEGQUALITY.Set((TWJQ)quality); + LogIt($"Set jpg quality to {quality}", sts); + if (!sts.IsSuccess) + { + quality = 85; + sts = _twain.Caps.ICAP_JPEGQUALITY.Set((TWJQ)quality); + LogIt($"Set jpg quality to {quality}", sts); + + if (!sts.IsSuccess) + { + sts = _twain.Caps.ICAP_JPEGQUALITY.Set(TWJQ.HIGH); + LogIt($"Set jpg quality to {TWJQ.HIGH}", sts); + } + } + } + } + } + } + LogIt(""); + } + + const ushort TWQC_MACHINE = 0x1000;// applies to entire session/machine + const ushort TWQC_BITONAL = 0x2000; // applies to Bitonal "cameras" + const ushort TWQC_COLOR = 0x4000; // applies to Color "cameras" + [Flags] + public enum TWQC2 : ushort + { + MACHINE = 0x1000, + BITONAL = 0x2000, + COLOR = 0x4000 + } + + private string FlattenFlag(TWQC val) + { + StringBuilder sb = new(); + + foreach (var type in Enum.GetValues(typeof(TWQC))) + { + if (((ushort)val & (ushort)type) > 0) + { + sb.Append(type).Append(", "); + } + } + foreach (var type in Enum.GetValues(typeof(TWQC2))) + { + if (((ushort)val & (ushort)type) > 0) + { + sb.Append(type).Append(", "); + } + } + if (sb.Length > 0) + { + sb.Length = sb.Length - 2; + } + return sb.ToString(); + } + + private void CaptureAsStandardScanner() + { + LogIt("Attempting Standard Scanner mode"); + + var sts = _twain.Caps.ICAP_PIXELTYPE.Set(TWPT.RGB); + LogIt("Set rgb pixel type", sts); + + if (_twain.Caps.CAP_DUPLEXENABLED.Supports.HasFlag(TWQC.SET)) + { + sts = _twain.Caps.CAP_DUPLEXENABLED.Set(TW_BOOL.True); + LogIt("Set duplex enabled", sts); + } + + var dpi = listDpi.SelectedValue == null ? 300 : Convert.ToInt32(listDpi.SelectedValue); + sts = _twain.Caps.ICAP_XRESOLUTION.Set(dpi); + LogIt("Set x-resolution", sts); + sts = _twain.Caps.ICAP_YRESOLUTION.Set(dpi); + LogIt("Set y-resolution", sts); + + if (listFormat.SelectedItem != null) + { + var format = (TWFF)listFormat.SelectedItem; + + sts = _twain.Caps.ICAP_IMAGEFILEFORMAT.Set(format); + LogIt($"Set {format} format.", sts); + + if (!sts.IsSuccess) + { + return; + } + + if (format != TWFF.BMP) + { + if (_twain.Caps.ICAP_COMPRESSION.Supports.HasFlag(TWQC.SET)) + { + sts = _twain.Caps.ICAP_COMPRESSION.Set(TWCP.JPEG); + LogIt("Set compression to jpg", sts); + if (sts.IsSuccess) + { + short quality = 90; + sts = _twain.Caps.ICAP_JPEGQUALITY.Set((TWJQ)quality); + LogIt($"Set jpg quality to {quality}", sts); + if (!sts.IsSuccess) + { + quality = 85; + sts = _twain.Caps.ICAP_JPEGQUALITY.Set((TWJQ)quality); + LogIt($"Set jpg quality to {quality}", sts); + + if (!sts.IsSuccess) + { + sts = _twain.Caps.ICAP_JPEGQUALITY.Set(TWJQ.HIGH); + LogIt($"Set jpg quality to {TWJQ.HIGH}", sts); + } + } + } + } + } + } + var limit = (short)boxLimit.Value; + sts = _twain.Caps.CAP_XFERCOUNT.Set(limit); + LogIt($"Set transfer limit {boxLimit.Value}", sts); + } + + private void btnStop_Click(object sender, EventArgs e) + { + _stopTransfer = true; + } + + private void btnBrowseFolder_Click(object sender, EventArgs e) + { + using FolderBrowserDialog dialog = new(); + if (dialog.ShowDialog() == DialogResult.OK) + { + boxFolder.Text = dialog.SelectedPath; + } + } + + private void btnOpenFolder_Click(object sender, EventArgs e) + { + if (EnsureBoxFolder()) + { + try + { + using var p = Process.Start("explorer.exe", boxFolder.Text); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } + + private bool EnsureBoxFolder() + { + if (!string.IsNullOrEmpty(boxFolder.Text)) + { + if (!Directory.Exists(boxFolder.Text)) + { + try + { + Directory.CreateDirectory(boxFolder.Text); + } + catch (Exception ex) + { + LogIt($"Failed to ensure save folder: {ex.Message}"); + return false; + } + } + return true; + } + return false; + } +} diff --git a/samples/ScannerTester/MainForm.resx b/samples/KodakTester/MainForm.resx similarity index 100% rename from samples/ScannerTester/MainForm.resx rename to samples/KodakTester/MainForm.resx diff --git a/samples/KodakTester/Program.cs b/samples/KodakTester/Program.cs new file mode 100644 index 0000000..2acb038 --- /dev/null +++ b/samples/KodakTester/Program.cs @@ -0,0 +1,16 @@ +namespace KodakTester; + +internal static class Program +{ + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + // To customize application configuration such as set high DPI settings or default font, + // see https://aka.ms/applicationconfiguration. + ApplicationConfiguration.Initialize(); + Application.Run(new MainForm()); + } +} \ No newline at end of file diff --git a/samples/ScannerTester/MainForm.cs b/samples/ScannerTester/MainForm.cs deleted file mode 100644 index 16cae77..0000000 --- a/samples/ScannerTester/MainForm.cs +++ /dev/null @@ -1,591 +0,0 @@ -using NTwain; -using NTwain.Data; -using NTwain.Data.Kds; -using NTwain.Triplets; -using System.ComponentModel; -using System.Diagnostics; -using System.Text; - -namespace ScannerTester -{ - public partial class MainForm : Form - { - TwainAppSession _twain; - private bool _stopTransfer; - - public MainForm() - { - InitializeComponent(); - - _twain = new TwainAppSession(); - _twain.TransferReady += _twain_TransferReady; - _twain.Transferred += _twain_Transferred; - _twain.SourceDisabled += _twain_SourceDisabled; - _twain.AddWinformFilter(); - } - - private void _twain_SourceDisabled(TwainAppSession sender, TW_IDENTITY_LEGACY e) - { - - } - - protected override void OnLoad(EventArgs e) - { - base.OnLoad(e); - _twain.OpenDSM(Handle, SynchronizationContext.Current!); - //_ = _twain.OpenDSMAsync(); - } - - protected override void OnFormClosed(FormClosedEventArgs e) - { - _twain.CloseDSM(); - //_ = _twain.CloseDSMAsync(); - base.OnFormClosed(e); - } - - private void _twain_Transferred(TwainAppSession sender, TransferredEventArgs e) - { - Invoke(() => - { - TW_EXTIMAGEINFO extInfo = TW_EXTIMAGEINFO.CreateRequest(TWEI.CAMERA); - e.GetExtendedImageInfo(ref extInfo); - string? camera = null; - foreach (var ei in extInfo.AsInfos()) - { - if (ei.ReturnCode == TWRC.SUCCESS) - { - switch (ei.InfoId) - { - //case (TWEI)KDS_TWEI.HDR_PAGENUMBER: - // LogIt($"TWEI_HDR_PAGENUMBER Value = {ei.ReadNonPointerData()}"); - // break; - case TWEI.CAMERA: - camera = ei.ReadHandleString(_twain); - LogIt($"{ei.InfoId} Value = {camera}"); - break; - } - } - else - { - LogIt($"{ei.InfoId} RC = {ei.ReturnCode}"); - } - } - extInfo.Free(_twain); - - if (e.Data != null) - { - LogIt($"Received {e.ImageInfo.PixelType} in {e.ImageInfo.Compression} compressed memory image."); - var folder = boxFolder.Text; - if (string.IsNullOrWhiteSpace(folder)) - { - folder = "Images"; - Directory.CreateDirectory(folder); - boxFolder.Text = folder; - } - var prefix = boxNamePrefix.Text; - if (string.IsNullOrWhiteSpace(prefix)) - { - prefix = "Capture_"; - boxNamePrefix.Text = prefix; - } - - using (var img = System.Drawing.Image.FromStream(e.Data.AsStream())) - { - //var saveFile = img.SaveToSmallestFormat(folder, prefix, lossless: false).ToString(); - //LogIt($"File saved to {saveFile}"); - } - } - else if (e.FileInfo != null) - { - var info = e.FileInfo.Value; - var path = info.FileName.ToString(); - LogIt($"Received {e.ImageInfo.PixelType} {info.Format} in {e.ImageInfo.Compression} compressed file {path}"); - } - e.Dispose(); - LogIt(""); - }); - } - - int _xferCount = 0; - private void _twain_TransferReady(TwainAppSession sender, TransferReadyEventArgs e) - { - Invoke(() => - { - if (_stopTransfer) - { - e.Cancel = CancelType.EndNow; - return; - } - - _xferCount++; - LogIt($"Got pending transfer with mode = {e.ImgXferMech}"); - if (e.ImgXferMech == TWSX.FILE) - { - var folder = boxFolder.Text; - if (string.IsNullOrWhiteSpace(folder)) - { - folder = "Images"; - Directory.CreateDirectory(folder); - boxFolder.Text = folder; - } - var prefix = boxNamePrefix.Text; - if (string.IsNullOrWhiteSpace(prefix)) - { - prefix = "Capture_"; - boxNamePrefix.Text = prefix; - } - - TWCP comp = TWCP.NONE; - TW_EXTIMAGEINFO extInfo = TW_EXTIMAGEINFO.CreateRequest((TWEI)KDS_TWEI.HDR_COMPRESSION); - e.GetExtendedImageInfo(ref extInfo); - foreach (var ei in extInfo.AsInfos()) - { - if (ei.ReturnCode == TWRC.SUCCESS) - { - switch (ei.InfoId) - { - case (TWEI)KDS_TWEI.HDR_COMPRESSION: - comp = ei.ReadNonPointerData(); - LogIt($"{ei.InfoId} Value = {comp}"); - break; - } - } - else - { - LogIt($"{ei.InfoId} RC = {ei.ReturnCode}"); - } - } - extInfo.Free(_twain); - - LogIt($"Compression at ready step = {comp}"); - string? targetName = $"{prefix}_{_xferCount:D4}"; - TWFF format = TWFF.TIFF; - switch (comp) - { - case TWCP.JPEG: - targetName = $"{prefix}_{_xferCount:D4}.jpg"; - format = TWFF.JFIF; - break; - case TWCP.NONE: - targetName = $"{prefix}_{_xferCount:D4}.bmp"; - format = TWFF.BMP; - break; - case TWCP.GROUP4: - default: - targetName = $"{prefix}_{_xferCount:D4}.tif"; - break; - } - TW_SETUPFILEXFER setup = new() - { - FileName = Path.Combine(folder, targetName), - Format = format - }; - - var sts = e.SetupFileTransfer(ref setup); - - LogIt($"Want to save image as {setup.Format} {setup.FileName}.", sts); - - var appId = _twain.AppIdentity; - var srcId = _twain.CurrentSource; - sts = _twain.WrapInSTS(DGControl.SetupFileXfer.Get(ref appId, ref srcId, out setup)); - - LogIt($"Checked actual file settings as {setup.Format} {setup.FileName}.", sts); - - } - LogIt(""); - }); - } - - protected override void OnFormClosing(FormClosingEventArgs e) - { - if (_twain.State > STATE.S5) - { - e.Cancel = true; - } - _twain.TryStepdown(STATE.S2); - base.OnFormClosing(e); - } - - private void btnSelectScanner_Click(object sender, EventArgs e) - { - var sts = _twain.ShowUserSelect(); - if (sts.IsSuccess && _twain.DefaultSource.Id > 0) - { - if (_twain.State > STATE.S3) - { - _twain.TryStepdown(STATE.S3); - } - sts = _twain.OpenSource(_twain.DefaultSource); - LogIt("Open scanner", sts); - if (sts.IsSuccess) - { - var src = _twain.CurrentSource; - lblCurScanner.Text = $"{src.ProductName} | v{src.Version} | protocol: {src.ProtocolMajor}.{src.ProtocolMinor}"; - LoadSettings(); - return; - } - } - - lblCurScanner.Text = "None selected"; - } - - private void LogIt(string msg) - { - boxLog.AppendText($"{msg}\n"); - } - private void LogIt(string msg, STS sts) - { - if (sts.IsSuccess) - { - boxLog.AppendText($"{msg} result = {sts.RC}\n"); - } - else - { - boxLog.AppendText($"{msg} result = {sts.RC} - {sts.ConditionCode}\n"); - } - } - - private void LoadSettings() - { - var mechs = _twain.Caps.ICAP_XFERMECH.Get().GetValues(); - - if (!mechs.Contains(TWSX.FILE)) - { - LogIt("File transfer is not supported."); - } - - var sts = _twain.Caps.ICAP_XFERMECH.Set(TWSX.FILE); - LogIt("Use file transfer", sts); - - if (_twain.Caps.ICAP_UNITS.GetCurrent().FirstOrDefault() != TWUN.INCHES) - { - sts = _twain.Caps.ICAP_UNITS.Set(TWUN.INCHES); - LogIt("Set unit to inches", sts); - } - - var dpis = _twain.Caps.ICAP_XRESOLUTION.Get().GetValues(); - listDpi.Items.Clear(); - if (dpis.Contains(200)) - { - listDpi.Items.Add(200); - listDpi.SelectedItem = 200; - } - else - { - LogIt("200 DPI doesn't appear to be supported."); - } - if (dpis.Contains(300)) - { - listDpi.Items.Add(300); - listDpi.SelectedItem = 300; - } - else - { - LogIt("300 DPI doesn't appear to be supported."); - } - - var formats = _twain.Caps.ICAP_IMAGEFILEFORMAT.Get().GetValues(); - listFormat.Items.Clear(); - foreach (var format in formats) - { - listFormat.Items.Add(format); - } - listFormat.SelectedItem = _twain.Caps.ICAP_IMAGEFILEFORMAT.GetCurrent().FirstOrDefault(); - - LogIt(""); - } - - private void btnDriverOnly_Click(object sender, EventArgs e) - { - if (_twain.State != STATE.S4) return; - - var sts = _twain.EnableSource(true, true); - LogIt("Show drivers", sts); - LogIt(""); - } - - private void btnTransfer_Click(object sender, EventArgs e) - { - if (_twain.State != STATE.S4 || !EnsureBoxFolder()) return; - - - var _isIndustrialKodak = _twain.CurrentSource.ProductName.ToString().StartsWith("KODAK Scanner: i"); - - if (_isIndustrialKodak) - { - CaptureAsKodakSDMI(); - } - else - { - CaptureAsStandardScanner(); - } - - _stopTransfer = false; - _xferCount = 0; - var sts = _twain.EnableSource(ckShowUI.Checked, false); - LogIt("Start capture", sts); - LogIt(""); - } - - private void CaptureAsKodakSDMI() - { - LogIt("Attempting Kodak SDMI mode"); - - LogIt($"Resolution supports {FlattenFlag(_twain.Caps.ICAP_XRESOLUTION.Supports)}"); - LogIt($"File format supports {FlattenFlag(_twain.Caps.ICAP_IMAGEFILEFORMAT.Supports)}"); - LogIt($"Compression supports {FlattenFlag(_twain.Caps.ICAP_COMPRESSION.Supports)}"); - LogIt($"EXTINFO supports {FlattenFlag(_twain.Caps.ICAP_EXTIMAGEINFO.Supports)}"); - - LogIt(""); - - var limit = (short)boxLimit.Value; - if (limit > 0) limit *= 2; - var sts = _twain.Caps.CAP_XFERCOUNT.Set(limit); - LogIt($"Set transfer limit {limit}", sts); - - sts = _twain.Caps.ICAP_EXTIMAGEINFO.Set(TW_BOOL.True); - LogIt($"Set extimageinfo enabled", sts); - - var format = (TWFF)listFormat.SelectedItem!; - sts = _twain.Caps.ICAP_IMAGEFILEFORMAT.Set(format); - LogIt($"Set {format} format.", sts); - - if (!sts.IsSuccess) - { - return; - } - - LogIt(""); - - var appId = _twain.AppIdentity; - var srcId = _twain.CurrentSource; - - - TW_FILESYSTEM fs = new() { InputName = "/Camera_Bitonal_Both" }; - sts = _twain.WrapInSTS(DGControl.FileSystem.ChangeDirectory(ref appId, ref srcId, ref fs)); - LogIt("Change to bw cameras", sts); - if (sts.IsSuccess) - { - sts = _twain.Caps.CAP_CAMERAENABLED.Set(TW_BOOL.True); - LogIt("Set camera enabled", sts); - - var dpi = listDpi.SelectedValue == null ? 300 : Convert.ToInt32(listDpi.SelectedValue); - sts = _twain.Caps.ICAP_XRESOLUTION.Set(dpi); - LogIt("Set x-resolution", sts); - sts = _twain.Caps.ICAP_YRESOLUTION.Set(dpi); - LogIt("Set y-resolution", sts); - - - if (format != TWFF.BMP) - { - LogIt($"Current format={_twain.Caps.ICAP_IMAGEFILEFORMAT.GetCurrent().First()}"); - LogIt($"Current compression={_twain.Caps.ICAP_COMPRESSION.GetCurrent().First()}"); - if (_twain.Caps.ICAP_COMPRESSION.Supports.HasFlag(TWQC.SET)) - { - sts = _twain.Caps.ICAP_COMPRESSION.Set(TWCP.GROUP4); - LogIt("Set compression to group4", sts); - } - } - } - LogIt(""); - - - fs = new() { FileType = (int)TWFY.CAMERA, InputName = "/Camera_Color_Both" }; sts = _twain.WrapInSTS(DGControl.FileSystem.ChangeDirectory(ref appId, ref srcId, ref fs)); - LogIt("Change to color cameras", sts); - if (sts.IsSuccess) - { - sts = _twain.Caps.CAP_CAMERAENABLED.Set(TW_BOOL.True); - LogIt("Set camera enabled", sts); - - - var dpi = listDpi.SelectedValue == null ? 300 : Convert.ToInt32(listDpi.SelectedValue); - sts = _twain.Caps.ICAP_XRESOLUTION.Set(dpi); - LogIt("Set x-resolution", sts); - sts = _twain.Caps.ICAP_YRESOLUTION.Set(dpi); - LogIt("Set y-resolution", sts); - - - if (format != TWFF.BMP) - { - LogIt($"Current format={_twain.Caps.ICAP_IMAGEFILEFORMAT.GetCurrent().First()}"); - LogIt($"Current compression={_twain.Caps.ICAP_COMPRESSION.GetCurrent().First()}"); - if (_twain.Caps.ICAP_COMPRESSION.Supports.HasFlag(TWQC.SET)) - { - sts = _twain.Caps.ICAP_COMPRESSION.Set(TWCP.JPEG); - LogIt("Set compression to jpg", sts); - if (sts.IsSuccess) - { - LogIt($"jpeg quality supports {FlattenFlag(_twain.Caps.ICAP_JPEGQUALITY.Supports)}"); - - short quality = 90; - sts = _twain.Caps.ICAP_JPEGQUALITY.Set((TWJQ)quality); - LogIt($"Set jpg quality to {quality}", sts); - if (!sts.IsSuccess) - { - quality = 85; - sts = _twain.Caps.ICAP_JPEGQUALITY.Set((TWJQ)quality); - LogIt($"Set jpg quality to {quality}", sts); - - if (!sts.IsSuccess) - { - sts = _twain.Caps.ICAP_JPEGQUALITY.Set(TWJQ.HIGH); - LogIt($"Set jpg quality to {TWJQ.HIGH}", sts); - } - } - } - } - } - } - LogIt(""); - } - - const ushort TWQC_MACHINE = 0x1000;// applies to entire session/machine - const ushort TWQC_BITONAL = 0x2000; // applies to Bitonal "cameras" - const ushort TWQC_COLOR = 0x4000; // applies to Color "cameras" - [Flags] - public enum TWQC2 : ushort - { - MACHINE = 0x1000, - BITONAL = 0x2000, - COLOR = 0x4000 - } - - private string FlattenFlag(TWQC val) - { - StringBuilder sb = new(); - - foreach (var type in Enum.GetValues(typeof(TWQC))) - { - if (((ushort)val & (ushort)type) > 0) - { - sb.Append(type).Append(", "); - } - } - foreach (var type in Enum.GetValues(typeof(TWQC2))) - { - if (((ushort)val & (ushort)type) > 0) - { - sb.Append(type).Append(", "); - } - } - if (sb.Length > 0) - { - sb.Length = sb.Length - 2; - } - return sb.ToString(); - } - - private void CaptureAsStandardScanner() - { - LogIt("Attempting Standard Scanner mode"); - - var sts = _twain.Caps.ICAP_PIXELTYPE.Set(TWPT.RGB); - LogIt("Set rgb pixel type", sts); - - if (_twain.Caps.CAP_DUPLEXENABLED.Supports.HasFlag(TWQC.SET)) - { - sts = _twain.Caps.CAP_DUPLEXENABLED.Set(TW_BOOL.True); - LogIt("Set duplex enabled", sts); - } - - var dpi = listDpi.SelectedValue == null ? 300 : Convert.ToInt32(listDpi.SelectedValue); - sts = _twain.Caps.ICAP_XRESOLUTION.Set(dpi); - LogIt("Set x-resolution", sts); - sts = _twain.Caps.ICAP_YRESOLUTION.Set(dpi); - LogIt("Set y-resolution", sts); - - if (listFormat.SelectedItem != null) - { - var format = (TWFF)listFormat.SelectedItem; - - sts = _twain.Caps.ICAP_IMAGEFILEFORMAT.Set(format); - LogIt($"Set {format} format.", sts); - - if (!sts.IsSuccess) - { - return; - } - - if (format != TWFF.BMP) - { - if (_twain.Caps.ICAP_COMPRESSION.Supports.HasFlag(TWQC.SET)) - { - sts = _twain.Caps.ICAP_COMPRESSION.Set(TWCP.JPEG); - LogIt("Set compression to jpg", sts); - if (sts.IsSuccess) - { - short quality = 90; - sts = _twain.Caps.ICAP_JPEGQUALITY.Set((TWJQ)quality); - LogIt($"Set jpg quality to {quality}", sts); - if (!sts.IsSuccess) - { - quality = 85; - sts = _twain.Caps.ICAP_JPEGQUALITY.Set((TWJQ)quality); - LogIt($"Set jpg quality to {quality}", sts); - - if (!sts.IsSuccess) - { - sts = _twain.Caps.ICAP_JPEGQUALITY.Set(TWJQ.HIGH); - LogIt($"Set jpg quality to {TWJQ.HIGH}", sts); - } - } - } - } - } - } - var limit = (short)boxLimit.Value; - sts = _twain.Caps.CAP_XFERCOUNT.Set(limit); - LogIt($"Set transfer limit {boxLimit.Value}", sts); - } - - private void btnStop_Click(object sender, EventArgs e) - { - _stopTransfer = true; - } - - private void btnBrowseFolder_Click(object sender, EventArgs e) - { - using FolderBrowserDialog dialog = new(); - if (dialog.ShowDialog() == DialogResult.OK) - { - boxFolder.Text = dialog.SelectedPath; - } - } - - private void btnOpenFolder_Click(object sender, EventArgs e) - { - if (EnsureBoxFolder()) - { - try - { - using var p = Process.Start("explorer.exe", boxFolder.Text); - } - catch (Exception ex) - { - MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - } - } - - private bool EnsureBoxFolder() - { - if (!string.IsNullOrEmpty(boxFolder.Text)) - { - if (!Directory.Exists(boxFolder.Text)) - { - try - { - Directory.CreateDirectory(boxFolder.Text); - } - catch (Exception ex) - { - LogIt($"Failed to ensure save folder: {ex.Message}"); - return false; - } - } - return true; - } - return false; - } - } -} diff --git a/samples/ScannerTester/Program.cs b/samples/ScannerTester/Program.cs deleted file mode 100644 index 6888a6e..0000000 --- a/samples/ScannerTester/Program.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace ScannerTester -{ - internal static class Program - { - /// - /// The main entry point for the application. - /// - [STAThread] - static void Main() - { - // To customize application configuration such as set high DPI settings or default font, - // see https://aka.ms/applicationconfiguration. - ApplicationConfiguration.Initialize(); - Application.Run(new MainForm()); - } - } -} \ No newline at end of file diff --git a/samples/WinConsole32/Program.cs b/samples/WinConsole32/Program.cs deleted file mode 100644 index 4f76e2c..0000000 --- a/samples/WinConsole32/Program.cs +++ /dev/null @@ -1,243 +0,0 @@ -using NTwain; -using NTwain.Data; -using NTwain.Data.Kds; -using System.Diagnostics; - -namespace WinConsole32 -{ - internal class Program - { - static async Task Main(string[] args) - { - var libVer = FileVersionInfo.GetVersionInfo(typeof(TwainAppSession).Assembly.Location).ProductVersion; - Console.WriteLine($"Console sample {(TWPlatform.Is32bit ? " 32bit" : " 64bit")} on NTwain {libVer}"); - - TwainAppSession twain = new TwainAppSession(); - - twain.StateChanged += Session_StateChanged; - twain.SourceDisabled += Session_SourceDisabled; - twain.TransferReady += Session_TransferReady; - twain.Transferred += Session_Transferred; - - var sts = await twain.OpenDSMAsync(); - - if (sts.IsSuccess) - { - Console.WriteLine("Available data sources:"); - - TW_IDENTITY_LEGACY firstSrc = default; - foreach (var src in twain.GetSources()) - { - if (!firstSrc.HasValue) firstSrc = src; - Console.WriteLine($"\t{src}"); - } - Console.WriteLine(); - - var defaultSrc = twain.DefaultSource; - Console.WriteLine($"Default data source = {defaultSrc}"); - Console.WriteLine(); - - sts = twain.ShowUserSelect(); - if (sts.IsSuccess) - { - Console.WriteLine($"Selected data source = {twain.DefaultSource}"); - Console.WriteLine(); - - var targetSrc = defaultSrc.HasValue ? defaultSrc : firstSrc; - - if (targetSrc.HasValue) - { - TestThisSource(twain, targetSrc); - } - else - { - Console.WriteLine("No data source to test."); - Console.WriteLine(); - } - - Console.WriteLine("---------------------------------------------"); - Console.WriteLine("Test in progress, press Enter to stop testing"); - Console.WriteLine("---------------------------------------------"); - Console.ReadLine(); - twain.TryStepdown(STATE.S1); - } - } - else - { - Console.WriteLine("Failed to attach: " + sts); - } - - Console.WriteLine("-------------------"); - Console.WriteLine("Press Enter to exit"); - Console.WriteLine("-------------------"); - Console.ReadLine(); - } - - private static void Session_TransferReady(TwainAppSession twain, TransferReadyEventArgs e) - { - if (e.ImgXferMech == TWSX.FILE) - { - var req = TW_EXTIMAGEINFO.CreateRequest(TWEI.CAMERA, (TWEI)KDS_TWEI.HDR_PAGENUMBER, (TWEI)KDS_TWEI.HDR_COMPRESSION); - e.GetExtendedImageInfo(ref req); - - string? camera = null; - TWCP comp = TWCP.NONE; - int pageNum = 0; - - foreach (var ei in req.AsInfos()) - { - switch (ei.InfoId) - { - case TWEI.CAMERA: - camera = ei.ReadHandleString(twain); - break; - case (TWEI)KDS_TWEI.HDR_PAGENUMBER: - pageNum = ei.ReadNonPointerData(); - break; - case (TWEI)KDS_TWEI.HDR_COMPRESSION: - comp = ei.ReadNonPointerData(); - break; - } - } - - string? targetName = null; - TWFF format = TWFF.TIFF; - switch (comp) - { - case TWCP.JPEG: - targetName = $"twain_{DateTime.Now:yyyyMMdd_HHmmss}_{xferCount:D4}.jpg"; - format = TWFF.JFIF; - break; - case TWCP.NONE: - targetName = $"twain_{DateTime.Now:yyyyMMdd_HHmmss}_{xferCount:D4}.bmp"; - format = TWFF.BMP; - break; - default: - targetName = $"twain_{DateTime.Now:yyyyMMdd_HHmmss}_{xferCount:D4}.tif"; - break; - } - - TW_SETUPFILEXFER setup = new() - { - FileName = Path.Combine("Images", targetName), - Format = format, - }; - e.SetupFileTransfer(ref setup); - } - } - - static int xferCount = 0; - static Stopwatch watch = new Stopwatch(); - private static void Session_Transferred(TwainAppSession twain, TransferredEventArgs e) - { - if (e.Data != null) - { - var saveFile = $"twain_{DateTime.Now:yyyyMMdd_HHmmss}_{xferCount}"; - Console.WriteLine($"SUCCESS! Got twain memory data #{++xferCount} on thread {Environment.CurrentManagedThreadId}, saving to {saveFile}."); - - using (var img = new ImageMagick.MagickImage(e.Data.AsStream())) - { - var format = ImageMagick.MagickFormat.Png; - if (img.ColorType == ImageMagick.ColorType.Palette) - { - // bw or gray - saveFile += ".png"; - } - else - { - // color - saveFile += ".jpg"; - format = ImageMagick.MagickFormat.Jpeg; - img.Settings.Compression = ImageMagick.CompressionMethod.JPEG; - img.Quality = (uint)85; - } - img.Write(saveFile, format); - } - } - else if (e.FileInfo != null) - { - var fi = e.FileInfo.Value; - Console.WriteLine($"SUCCESS! Got twain file data #{++xferCount} on thread {Environment.CurrentManagedThreadId} as {fi.FileName}."); - } - else - { - Console.WriteLine($"BUMMER! No twain data #{++xferCount} on thread {Environment.CurrentManagedThreadId}."); - } - e.Dispose(); - } - - private static void Session_StateChanged(TwainAppSession twain, STATE e) - { - Console.WriteLine($"Session state changed to {twain.State}"); - } - - private static void Session_SourceDisabled(TwainAppSession twain, TW_IDENTITY_LEGACY e) - { - watch.Stop(); - var elapsed = watch.Elapsed; - Console.WriteLine($"Session source disabled, took {elapsed}, will retest in 3 sec..."); - - Thread.Sleep(3000); - if (twain.State > STATE.S3) - TestThisSource(twain, e); - } - - private static void TestThisSource(TwainAppSession twain, TW_IDENTITY_LEGACY source) - { - Console.WriteLine($"Testing data source {source}"); - Console.WriteLine(); - - if (twain.State == STATE.S3) twain.OpenSource(source); - - if (source.ProductName.ToString().StartsWith("KODAK Scanner:")) - { - TryKodakSDMI(twain); - } - else - { - twain.Caps.ICAP_XFERMECH.Set(TWSX.NATIVE); - twain.Caps.ICAP_PIXELTYPE.Set(TWPT.RGB); - twain.Caps.ICAP_XRESOLUTION.Set(300f); - twain.Caps.ICAP_YRESOLUTION.Set(300f); - twain.Caps.CAP_XFERCOUNT.Set(4); - - xferCount = 0; - watch.Restart(); - var rc = twain.EnableSource(true, false); - } - } - - private static void TryKodakSDMI(TwainAppSession twain) - { - twain.Caps.ICAP_XFERMECH.Set(TWSX.FILE); - - twain.Caps.ICAP_EXTIMAGEINFO.Set(TW_BOOL.True); - //twain.Caps.ICAP_IMAGEFILEFORMAT.Set(TWFF.TIFF); - - var orders = twain.Caps.CAP_CAMERAORDER.GetCurrent().Cast().ToList(); - - - if (twain.ChangeFileSystemDirectory(TWFY.CAMERA, "/Camera_Bitonal_Both").IsSuccess) - { - twain.Caps.CAP_CAMERAENABLED.Set(TW_BOOL.True); - twain.Caps.ICAP_XRESOLUTION.Set(300f); - twain.Caps.ICAP_YRESOLUTION.Set(300f); - twain.Caps.ICAP_COMPRESSION.Set(TWCP.GROUP4); - } - - if (twain.ChangeFileSystemDirectory(TWFY.CAMERA, "/Camera_Color_Both").IsSuccess) - { - twain.Caps.CAP_CAMERAENABLED.Set(TW_BOOL.True); - twain.Caps.ICAP_XRESOLUTION.Set(300f); - twain.Caps.ICAP_YRESOLUTION.Set(300f); - twain.Caps.ICAP_COMPRESSION.Set(TWCP.JPEG); - twain.Caps.ICAP_JPEGQUALITY.Set(TWJQ.HIGH); - } - twain.Caps.CAP_XFERCOUNT.Set(4); - - xferCount = 0; - watch = Stopwatch.StartNew(); - var rc = twain.EnableSource(false, false); - } - } -} \ No newline at end of file diff --git a/samples/WinConsole32/WinConsole32.csproj b/samples/WinConsole32/WinConsole32.csproj deleted file mode 100644 index 6299f13..0000000 --- a/samples/WinConsole32/WinConsole32.csproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - Exe - net472 - enable - x86 - enable - 12 - true - - - - - - - - - - - diff --git a/samples/WinForm32/ControlExtensions.cs b/samples/WinForm32/ControlExtensions.cs index ee36178..bafb9a7 100644 --- a/samples/WinForm32/ControlExtensions.cs +++ b/samples/WinForm32/ControlExtensions.cs @@ -6,15 +6,14 @@ using System.Text; using System.Threading.Tasks; using System.Windows.Forms; -namespace WinFormSample +namespace WinFormSample; + +static class ControlExtensions { - static class ControlExtensions - { public static void SetDoubleBufferedAsNeeded(this Control control) { - var dbprop = control.GetType().GetProperty("DoubleBuffered", BindingFlags.NonPublic | BindingFlags.Instance); - dbprop!.SetValue(control, !SystemInformation.TerminalServerSession); + var dbprop = control.GetType().GetProperty("DoubleBuffered", BindingFlags.NonPublic | BindingFlags.Instance); + dbprop!.SetValue(control, !SystemInformation.TerminalServerSession); } - } } diff --git a/samples/WinForm32/Form1.cs b/samples/WinForm32/Form1.cs index cc9de27..eeebfb9 100644 --- a/samples/WinForm32/Form1.cs +++ b/samples/WinForm32/Form1.cs @@ -2,6 +2,7 @@ using Microsoft.Win32; using NTwain; using NTwain.Caps; using NTwain.Data; +using NTwain.Events; using System; using System.Collections.Generic; using System.ComponentModel; @@ -38,7 +39,7 @@ public partial class Form1 : Form TWPlatform.PreferLegacyDSM = false; - twain = new TwainAppSession(); + twain = new TwainAppSession(appThreadContext: SynchronizationContext.Current); twain.StateChanged += Twain_StateChanged; twain.DefaultSourceChanged += Twain_DefaultSourceChanged; twain.CurrentSourceChanged += Twain_CurrentSourceChanged; @@ -62,16 +63,13 @@ public partial class Form1 : Form _jpegEncoder = ImageCodecInfo.GetImageEncoders().First(enc => enc.FormatID == ImageFormat.Jpeg.Guid); } - private void Twain_SourceDisabled(TwainAppSession sender, TW_IDENTITY_LEGACY e) + private void Twain_SourceDisabled(TwainAppSession sender, TWIdentityWrapper e) { - BeginInvoke(() => + if (watch.IsRunning) { - if (watch.IsRunning) - { - watch.Stop(); - MessageBox.Show($"Took {watch.Elapsed} to finish that transfer."); - } - }); + watch.Stop(); + MessageBox.Show($"Took {watch.Elapsed} to finish that transfer."); + } } private void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e) @@ -86,29 +84,18 @@ public partial class Form1 : Form } } - protected override async void OnHandleCreated(EventArgs e) + protected override void OnLoad(EventArgs e) { - base.OnHandleCreated(e); + base.OnLoad(e); - if (useDiyPump) - { - var sts = await twain.OpenDSMAsync(); - Debug.WriteLine($"OpenDSMAsync={sts}"); - } - else - { - var hwnd = this.Handle; - var sts = twain.OpenDSM(hwnd, SynchronizationContext.Current!); - twain.AddWinformFilter(); - Debug.WriteLine($"OpenDSM={sts}"); - } + var sts = twain.OpenDsm(); + Debug.WriteLine($"OpenDSMAsync={sts}"); } protected override void OnFormClosing(FormClosingEventArgs e) { var finalState = twain.TryStepdown(STATE.S2); Debug.WriteLine($"Stepdown result state={finalState}"); - twain.RemoveWinformFilter(); base.OnFormClosing(e); } @@ -224,44 +211,41 @@ public partial class Form1 : Form Debug.WriteLine($"[thread {Environment.CurrentManagedThreadId}] transfer ready."); } - private void Twain_DefaultSourceChanged(TwainAppSession sender, TW_IDENTITY_LEGACY ds) + private void Twain_DefaultSourceChanged(TwainAppSession sender, TWIdentityWrapper? ds) { - BeginInvoke(() => lblDefault.Text = ds.ProductName); + lblDefault.Text = ds?.ProductName; } private void Twain_StateChanged(TwainAppSession sender, STATE state) { - BeginInvoke(() => lblState.Text = state.ToString()); + lblState.Text = state.ToString(); } - private void Twain_CurrentSourceChanged(TwainAppSession sender, TW_IDENTITY_LEGACY ds) + private void Twain_CurrentSourceChanged(TwainAppSession sender, TWIdentityWrapper? ds) { - BeginInvoke(() => + lblCurrent.Text = ds?.ToString(); + if (twain.State == STATE.S4) { - lblCurrent.Text = ds.ToString(); - if (twain.State == STATE.S4) - { - LoadCapInfoList(); + LoadCapInfoList(); - // never seen a driver support these but here it is to test it - if (twain.GetCapLabel(CAP.ICAP_SUPPORTEDSIZES, out string? test).RC == TWRC.SUCCESS) - { - Debug.WriteLine($"Supported sizes label from ds = {test}"); - } - if (twain.GetCapHelp(CAP.ICAP_SUPPORTEDSIZES, out string? test2).RC == TWRC.SUCCESS) - { - Debug.WriteLine($"Supported sizes help from ds = {test2}"); - } - if (twain.GetCapLabelEnum(CAP.ICAP_SUPPORTEDSIZES, out IList? test3).RC == TWRC.SUCCESS && test3 != null) - { - Debug.WriteLine($"Supported sizes label enum from ds = {string.Join(Environment.NewLine, test3)}"); - } - } - else + // never seen a driver support these but here it is to test it + if (twain.GetCapLabel(CAP.ICAP_SUPPORTEDSIZES, out string? test).RC == TWRC.SUCCESS) { - capListView.Items.Clear(); + Debug.WriteLine($"Supported sizes label from ds = {test}"); } - }); + if (twain.GetCapHelp(CAP.ICAP_SUPPORTEDSIZES, out string? test2).RC == TWRC.SUCCESS) + { + Debug.WriteLine($"Supported sizes help from ds = {test2}"); + } + if (twain.GetCapLabelEnum(CAP.ICAP_SUPPORTEDSIZES, out IList? test3).RC == TWRC.SUCCESS && test3 != null) + { + Debug.WriteLine($"Supported sizes label enum from ds = {string.Join(Environment.NewLine, test3)}"); + } + } + else + { + capListView.Items.Clear(); + } } private void LoadCapInfoList() @@ -277,7 +261,7 @@ public partial class Form1 : Form if (twain.GetCapCurrent(c, out TW_CAPABILITY twcap).RC == TWRC.SUCCESS) { var enumType = SizeAndConversionUtils.GetEnumType(c); - var realType = twcap.DetermineValueType(twain); + var realType = twcap.DetermineValueType(twain.MemoryManager); it.SubItems.Add(enumType?.Name.ToString() ?? realType.ToString()); it.SubItems.Add(ReadTypedValue(c, enumType, realType, forCurrent: true)); it.SubItems.Add(ReadTypedValue(c, enumType, realType, forCurrent: false)); @@ -441,7 +425,7 @@ public partial class Form1 : Form private void btnSetDef_Click(object sender, EventArgs e) { - if (listSources.SelectedItem is TW_IDENTITY_LEGACY ds) + if (listSources.SelectedItem is TWIdentityWrapper ds) { twain.SetDefaultSource(ds); } @@ -449,7 +433,7 @@ public partial class Form1 : Form private void btnOpen_Click(object sender, EventArgs e) { - if (listSources.SelectedItem is TW_IDENTITY_LEGACY ds) + if (listSources.SelectedItem is TWIdentityWrapper ds) { twain.TryStepdown(STATE.S3); @@ -466,17 +450,22 @@ public partial class Form1 : Form { twain.TryStepdown(STATE.S3); + if (twain.DefaultSource == null) + { + MessageBox.Show("No default source set."); + return; + } twain.OpenSource(twain.DefaultSource); } private void btnShowSettings_Click(object sender, EventArgs e) { - twain.EnableSource(true, true); + twain.EnableSource(SourceEnableOption.UIOnly); } private void btnStart_Click(object sender, EventArgs e) { - if (twain.EnableSource(ckShowUI.Checked, false).IsSuccess) + if (twain.EnableSource(ckShowUI.Checked ? SourceEnableOption.ShowUI : SourceEnableOption.NoUI).IsSuccess) { _useThreadForImag = ckBgImageHandling.Checked; _useSystemDrawing = ckSystemDrawing.Checked; diff --git a/samples/WinForm32/NoOpStream.cs b/samples/WinForm32/NoOpStream.cs index 9e72ca6..d14011c 100644 --- a/samples/WinForm32/NoOpStream.cs +++ b/samples/WinForm32/NoOpStream.cs @@ -5,10 +5,10 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace WinFormSample +namespace WinFormSample; + +internal class NoOpStream : Stream { - internal class NoOpStream : Stream - { public override bool CanRead => false; public override bool CanSeek => false; @@ -25,12 +25,12 @@ namespace WinFormSample public override int Read(byte[] buffer, int offset, int count) { - throw new NotImplementedException(); + throw new NotImplementedException(); } public override long Seek(long offset, SeekOrigin origin) { - throw new NotImplementedException(); + throw new NotImplementedException(); } public override void SetLength(long value) @@ -40,5 +40,4 @@ namespace WinFormSample public override void Write(byte[] buffer, int offset, int count) { } - } } diff --git a/samples/WinForm32/Program.cs b/samples/WinForm32/Program.cs index d22ac4d..c9ebae1 100644 --- a/samples/WinForm32/Program.cs +++ b/samples/WinForm32/Program.cs @@ -7,39 +7,38 @@ using System.Runtime.ExceptionServices; using System.Text; using System.Windows.Forms; -namespace WinFormSample -{ - internal static class Program - { - /// - /// The main entry point for the application. - /// - [STAThread] - [HandleProcessCorruptedStateExceptions] - static void Main() - { - //if (DsmLoader.TryUseCustomDSM()) - //{ - // Debug.WriteLine("Using our own dsm now :)"); - //} - //else - //{ - // Debug.WriteLine("Will attempt to use default dsm :("); - //} +namespace WinFormSample; - // To customize application configuration such as set high DPI settings or default font, - // see https://aka.ms/applicationconfiguration. - try - { - ApplicationConfiguration.Initialize(); - Application.Run(new Form1()); - } - catch (Exception ex) - { - if (!Debugger.IsAttached) Debugger.Launch(); - Debugger.Break(); - Debug.WriteLine("Unhandled exception: " + ex.ToString()); - } +internal static class Program +{ + /// + /// The main entry point for the application. + /// + [STAThread] + //[HandleProcessCorruptedStateExceptions] + static void Main() + { + //if (DsmLoader.TryUseCustomDSM()) + //{ + // Debug.WriteLine("Using our own dsm now :)"); + //} + //else + //{ + // Debug.WriteLine("Will attempt to use default dsm :("); + //} + + // To customize application configuration such as set high DPI settings or default font, + // see https://aka.ms/applicationconfiguration. + try + { + ApplicationConfiguration.Initialize(); + Application.Run(new Form1()); + } + catch (Exception ex) + { + if (!Debugger.IsAttached) Debugger.Launch(); + Debugger.Break(); + Debug.WriteLine("Unhandled exception: " + ex.ToString()); } } } \ No newline at end of file diff --git a/samples/WinForm32/WinForm32.csproj b/samples/WinForm32/WinForm32.csproj index 1e9b1ae..8113a01 100644 --- a/samples/WinForm32/WinForm32.csproj +++ b/samples/WinForm32/WinForm32.csproj @@ -2,7 +2,7 @@ WinExe - net10.0-windows7.0 + net10.0-windows enable true x86 @@ -23,6 +23,9 @@ PreserveNewest + + PreserveNewest + \ No newline at end of file diff --git a/samples/WinForm32/runtimes/win-x86/native/TWAINDSM.dll b/samples/WinForm32/runtimes/win-x86/native/TWAINDSM.dll new file mode 100644 index 0000000000000000000000000000000000000000..7f38f2f5678e4f4c2a6107525a2411ae32c6b188 GIT binary patch literal 176544 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 literal 0 HcmV?d00001 diff --git a/samples/WinForm64/WinForm64.csproj b/samples/WinForm64/WinForm64.csproj index cedc41b..bfb8b80 100644 --- a/samples/WinForm64/WinForm64.csproj +++ b/samples/WinForm64/WinForm64.csproj @@ -2,7 +2,7 @@ WinExe - net10.0-windows7.0 + net10.0-windows enable true x64 diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 0d5130b..1661bbc 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -2,21 +2,21 @@ 4.0.0.0 - alpha.31 + beta.1 4.0.0.0 $(VersionPrefix) - https://github.com/soukoku/ntwain + https://github.com/soukoku/ntwain5 twain scan MIT Scanner-Icon.png - https://github.com/soukoku/ntwain + https://github.com/soukoku/ntwain5 GIT en-US - Eugene Wang 2012-2025 + Eugene Wang 2012-2026 Eugene Wang 12 @@ -26,7 +26,6 @@ true - true true true $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb diff --git a/src/NTwain/DSM/DSMGenerator.tt b/src/NTwain/DSM/DSMGenerator.tt index be99d7b..6d9c440 100644 --- a/src/NTwain/DSM/DSMGenerator.tt +++ b/src/NTwain/DSM/DSMGenerator.tt @@ -22,13 +22,13 @@ using NTwain.Data; using System; using System.Runtime.InteropServices; -namespace NTwain.DSM +namespace NTwain.DSM; + +/// +/// Low-level pinvoke methods using <#= file.dllPath #>. <#= file.addlInfo #> +/// +public static partial class <#= file.className #> { - /// - /// Low-level pinvoke methods using <#= file.dllPath #>. <#= file.addlInfo #> - /// - public static partial class <#= file.className #> - { const string DsmName = "<#= file.dllPath #>"; #if NET7_0_OR_GREATER @@ -399,8 +399,8 @@ namespace NTwain.DSM ref <#= file.identityClass #> origin, ref <#= file.identityClass #> dest, DG dg, DAT dat, MSG msg, ref TW_RGBRESPONSE resp ); - } } + <# SaveOutput(file.className + ".cs"); }#> diff --git a/src/NTwain/DSM/DsmLoader.cs b/src/NTwain/DSM/DsmLoader.cs index ce03e34..deaaf60 100644 --- a/src/NTwain/DSM/DsmLoader.cs +++ b/src/NTwain/DSM/DsmLoader.cs @@ -1,63 +1,58 @@ -using Microsoft.Extensions.Logging; -using NTwain.Data; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; +//using Microsoft.Extensions.Logging; +//using NTwain.Data; +//using System; +//using System.Diagnostics; +//using System.IO; +//using System.Reflection; +//using System.Runtime.InteropServices; -namespace NTwain.DSM -{ - /// - /// For demoing loading dsm from custom path in case - /// it's not installed on system and don't want to be - /// placed besides the exe. - /// - static class DsmLoader - { - static IntPtr __dllPtr; +//namespace NTwain.DSM; - public static bool TryLoadCustomDSM(ILogger logger) - { - if (__dllPtr == IntPtr.Zero) - { -#if NETFRAMEWORK - var curFile = Assembly.GetExecutingAssembly().Location; - if (string.IsNullOrEmpty(curFile)) - { - using var proc = Process.GetCurrentProcess(); - curFile = proc.MainModule.FileName; - } - var folder = Path.GetDirectoryName(curFile); -#else - var folder = AppContext.BaseDirectory; -#endif - if (!string.IsNullOrEmpty(folder)) - { - var dll = Path.Combine( - folder, - $@"runtimes\win-{(TWPlatform.Is32bit ? "x86" : "x64")}\native\TWAINDSM.dll"); +///// +///// For demoing loading dsm from custom path in case +///// it's not installed on system and don't want to be +///// placed besides the exe. +///// +//static class DsmLoader +//{ +// static IntPtr __dllPtr; - __dllPtr = LoadLibraryW(dll); - } +// public static bool TryLoadCustomDSM(ILogger logger) +// { +// if (__dllPtr == IntPtr.Zero) +// { +//#if NETFRAMEWORK +// var curFile = Assembly.GetExecutingAssembly().Location; +// if (string.IsNullOrEmpty(curFile)) +// { +// using var proc = Process.GetCurrentProcess(); +// curFile = proc.MainModule.FileName; +// } +// var folder = Path.GetDirectoryName(curFile); +//#else +// var folder = AppContext.BaseDirectory; +//#endif +// if (!string.IsNullOrEmpty(folder)) +// { +// var dll = Path.Combine( +// folder, +// $@"runtimes\win-{(TWPlatform.Is32bit ? "x86" : "x64")}\native\TWAINDSM.dll"); - if (__dllPtr != IntPtr.Zero) - { - logger.LogTrace("Using our own dsm now :)"); - } - else - { - logger.LogTrace("Will attempt to use default dsm :("); - } - } - return __dllPtr != IntPtr.Zero; - } +// __dllPtr = LoadLibraryW(dll); +// } - [DllImport("kernel32", SetLastError = true)] - static extern IntPtr LoadLibraryW([MarshalAs(UnmanagedType.LPWStr)] string lpFileName); - } -} +// if (__dllPtr != IntPtr.Zero) +// { +// logger.LogTrace("Using our own dsm now :)"); +// } +// else +// { +// logger.LogTrace("Will attempt to use default dsm :("); +// } +// } +// return __dllPtr != IntPtr.Zero; +// } + +// [DllImport("kernel32", SetLastError = true)] +// static extern IntPtr LoadLibraryW([MarshalAs(UnmanagedType.LPWStr)] string lpFileName); +//} diff --git a/src/NTwain/DSM/Linux64DSM.cs b/src/NTwain/DSM/Linux64DSM.cs index 24183e4..b93a824 100644 --- a/src/NTwain/DSM/Linux64DSM.cs +++ b/src/NTwain/DSM/Linux64DSM.cs @@ -2,13 +2,13 @@ using NTwain.Data; using System; using System.Runtime.InteropServices; -namespace NTwain.DSM +namespace NTwain.DSM; + +/// +/// Low-level pinvoke methods using /usr/local/lib64/libtwaindsm.so. For versions since 2.4. +/// +public static partial class Linux64DSM { - /// - /// Low-level pinvoke methods using /usr/local/lib64/libtwaindsm.so. For versions since 2.4. - /// - public static partial class Linux64DSM - { const string DsmName = "/usr/local/lib64/libtwaindsm.so"; #if NET7_0_OR_GREATER @@ -367,5 +367,5 @@ namespace NTwain.DSM ref TW_IDENTITY_LEGACY origin, ref TW_IDENTITY_LEGACY dest, DG dg, DAT dat, MSG msg, ref TW_RGBRESPONSE resp ); - } } + diff --git a/src/NTwain/DSM/LinuxBotched64DSM.cs b/src/NTwain/DSM/LinuxBotched64DSM.cs index 763424c..524aad2 100644 --- a/src/NTwain/DSM/LinuxBotched64DSM.cs +++ b/src/NTwain/DSM/LinuxBotched64DSM.cs @@ -2,13 +2,13 @@ using NTwain.Data; using System; using System.Runtime.InteropServices; -namespace NTwain.DSM +namespace NTwain.DSM; + +/// +/// Low-level pinvoke methods using /usr/local/lib/libtwaindsm.so.2.3.2. For versions before 2.4. +/// +public static partial class LinuxBotched64DSM { - /// - /// Low-level pinvoke methods using /usr/local/lib/libtwaindsm.so.2.3.2. For versions before 2.4. - /// - public static partial class LinuxBotched64DSM - { const string DsmName = "/usr/local/lib/libtwaindsm.so.2.3.2"; #if NET7_0_OR_GREATER @@ -367,5 +367,5 @@ namespace NTwain.DSM ref TW_IDENTITY origin, ref TW_IDENTITY dest, DG dg, DAT dat, MSG msg, ref TW_RGBRESPONSE resp ); - } } + diff --git a/src/NTwain/DSM/LinuxDSM.cs b/src/NTwain/DSM/LinuxDSM.cs index d3cd359..0737c1a 100644 --- a/src/NTwain/DSM/LinuxDSM.cs +++ b/src/NTwain/DSM/LinuxDSM.cs @@ -2,13 +2,13 @@ using NTwain.Data; using System; using System.Runtime.InteropServices; -namespace NTwain.DSM +namespace NTwain.DSM; + +/// +/// Low-level pinvoke methods using /usr/local/lib/libtwaindsm.so. +/// +public static partial class LinuxDSM { - /// - /// Low-level pinvoke methods using /usr/local/lib/libtwaindsm.so. - /// - public static partial class LinuxDSM - { const string DsmName = "/usr/local/lib/libtwaindsm.so"; #if NET7_0_OR_GREATER @@ -367,5 +367,5 @@ namespace NTwain.DSM ref TW_IDENTITY_LEGACY origin, ref TW_IDENTITY_LEGACY dest, DG dg, DAT dat, MSG msg, ref TW_RGBRESPONSE resp ); - } } + diff --git a/src/NTwain/DSM/OSXLegacyDSM.cs b/src/NTwain/DSM/OSXLegacyDSM.cs index 60eb798..f2f9b90 100644 --- a/src/NTwain/DSM/OSXLegacyDSM.cs +++ b/src/NTwain/DSM/OSXLegacyDSM.cs @@ -2,13 +2,13 @@ using NTwain.Data; using System; using System.Runtime.InteropServices; -namespace NTwain.DSM +namespace NTwain.DSM; + +/// +/// Low-level pinvoke methods using /System/Library/Frameworks/framework/TWAIN. +/// +public static partial class OSXLegacyDSM { - /// - /// Low-level pinvoke methods using /System/Library/Frameworks/framework/TWAIN. - /// - public static partial class OSXLegacyDSM - { const string DsmName = "/System/Library/Frameworks/framework/TWAIN"; #if NET7_0_OR_GREATER @@ -367,5 +367,5 @@ namespace NTwain.DSM ref TW_IDENTITY_MACOSX origin, ref TW_IDENTITY_MACOSX dest, DG dg, DAT dat, MSG msg, ref TW_RGBRESPONSE resp ); - } } + diff --git a/src/NTwain/DSM/OSXNewDSM.cs b/src/NTwain/DSM/OSXNewDSM.cs index 72b46fd..3b856c6 100644 --- a/src/NTwain/DSM/OSXNewDSM.cs +++ b/src/NTwain/DSM/OSXNewDSM.cs @@ -2,13 +2,13 @@ using NTwain.Data; using System; using System.Runtime.InteropServices; -namespace NTwain.DSM +namespace NTwain.DSM; + +/// +/// Low-level pinvoke methods using /Library/Frameworks/TWAINDSM.framework/TWAINDSM. +/// +public static partial class OSXNewDSM { - /// - /// Low-level pinvoke methods using /Library/Frameworks/TWAINDSM.framework/TWAINDSM. - /// - public static partial class OSXNewDSM - { const string DsmName = "/Library/Frameworks/TWAINDSM.framework/TWAINDSM"; #if NET7_0_OR_GREATER @@ -367,5 +367,5 @@ namespace NTwain.DSM ref TW_IDENTITY_MACOSX origin, ref TW_IDENTITY_MACOSX dest, DG dg, DAT dat, MSG msg, ref TW_RGBRESPONSE resp ); - } } + diff --git a/src/NTwain/DSM/WinLegacyDSM.cs b/src/NTwain/DSM/WinLegacyDSM.cs index aa77407..779544d 100644 --- a/src/NTwain/DSM/WinLegacyDSM.cs +++ b/src/NTwain/DSM/WinLegacyDSM.cs @@ -2,13 +2,13 @@ using NTwain.Data; using System; using System.Runtime.InteropServices; -namespace NTwain.DSM +namespace NTwain.DSM; + +/// +/// Low-level pinvoke methods using twain_32.dll. For 32bit only. +/// +public static partial class WinLegacyDSM { - /// - /// Low-level pinvoke methods using twain_32.dll. For 32bit only. - /// - public static partial class WinLegacyDSM - { const string DsmName = "twain_32.dll"; #if NET7_0_OR_GREATER @@ -367,5 +367,5 @@ namespace NTwain.DSM ref TW_IDENTITY_LEGACY origin, ref TW_IDENTITY_LEGACY dest, DG dg, DAT dat, MSG msg, ref TW_RGBRESPONSE resp ); - } } + diff --git a/src/NTwain/DSM/WinNewDSM.cs b/src/NTwain/DSM/WinNewDSM.cs index 88c6587..4fc7d9d 100644 --- a/src/NTwain/DSM/WinNewDSM.cs +++ b/src/NTwain/DSM/WinNewDSM.cs @@ -2,13 +2,13 @@ using NTwain.Data; using System; using System.Runtime.InteropServices; -namespace NTwain.DSM +namespace NTwain.DSM; + +/// +/// Low-level pinvoke methods using twaindsm.dll. +/// +public static partial class WinNewDSM { - /// - /// Low-level pinvoke methods using twaindsm.dll. - /// - public static partial class WinNewDSM - { const string DsmName = "twaindsm.dll"; #if NET7_0_OR_GREATER @@ -367,5 +367,5 @@ namespace NTwain.DSM ref TW_IDENTITY_LEGACY origin, ref TW_IDENTITY_LEGACY dest, DG dg, DAT dat, MSG msg, ref TW_RGBRESPONSE resp ); - } } + diff --git a/src/NTwain/Data/BufferedData.cs b/src/NTwain/Data/BufferedData.cs index 047d36c..12fd072 100644 --- a/src/NTwain/Data/BufferedData.cs +++ b/src/NTwain/Data/BufferedData.cs @@ -2,13 +2,13 @@ using System.Buffers; using System.IO; -namespace NTwain.Data +namespace NTwain.Data; + +/// +/// Simple thing with shared bytes buffer and the valid data length. +/// +public class BufferedData : IDisposable { - /// - /// Simple thing with shared bytes buffer and the valid data length. - /// - public class BufferedData : IDisposable - { // experiment using array pool for things transferred in memory. // this can pool up to a "normal" max of legal size paper in 24 bit at 300 dpi (~31MB) // so the array max is made with 32 MB. Typical usage should be a lot less. @@ -16,16 +16,16 @@ namespace NTwain.Data internal BufferedData(int size) { - _buffer = MemPool.Rent(size); - _length = size; - _fromPool = true; + _buffer = MemPool.Rent(size); + _length = size; + _fromPool = true; } internal BufferedData(byte[] data, int size, bool fromPool) { - _buffer = data; - _length = size; - _fromPool = fromPool; + _buffer = data; + _length = size; + _fromPool = fromPool; } bool _disposed; @@ -49,8 +49,8 @@ namespace NTwain.Data /// public ReadOnlySpan AsSpan() { - if (_disposed) throw new ObjectDisposedException(GetType().FullName); - return _buffer.AsSpan(0, _length); + if (_disposed) throw new ObjectDisposedException(GetType().FullName); + return _buffer.AsSpan(0, _length); } /// @@ -60,8 +60,8 @@ namespace NTwain.Data /// public ReadOnlyMemory AsMemory() { - if (_disposed) throw new ObjectDisposedException(GetType().FullName); - return _buffer.AsMemory(0, _length); + if (_disposed) throw new ObjectDisposedException(GetType().FullName); + return _buffer.AsMemory(0, _length); } /// @@ -71,22 +71,21 @@ namespace NTwain.Data /// public Stream AsStream() { - if (_disposed) throw new ObjectDisposedException(GetType().FullName); - return new MemoryStream(_buffer, 0, _length, false); + if (_disposed) throw new ObjectDisposedException(GetType().FullName); + return new MemoryStream(_buffer, 0, _length, false); } public void Dispose() { - if (_fromPool && _disposed) - { - MemPool.Return(_buffer); - _disposed = true; - } + if (_fromPool && _disposed) + { + MemPool.Return(_buffer); + _disposed = true; + } } public static implicit operator ReadOnlySpan(BufferedData value) => value.AsSpan(); public static implicit operator ReadOnlyMemory(BufferedData value) => value.AsMemory(); public static implicit operator Stream(BufferedData value) => value.AsStream(); - } } diff --git a/src/NTwain/Data/README.md b/src/NTwain/Data/README.md deleted file mode 100644 index daaeb52..0000000 --- a/src/NTwain/Data/README.md +++ /dev/null @@ -1,11 +0,0 @@ -This namespace contains types and utilities that were modified -from the [twaincs project](https://github.com/twain/twain-cs). - -Version initially used is 2.5.0.0. - -I just couldn't trust myself with making correct struct definitions -so used those instead. - -The `TWAINH.cs` file are minimally modified so they could be updated -easily should I need to. Most modifications are added in -`TWAINH_EXTRAS.cs.` diff --git a/src/NTwain/Data/SizeAndConversionUtils.cs b/src/NTwain/Data/SizeAndConversionUtils.cs index c47be72..50a5efa 100644 --- a/src/NTwain/Data/SizeAndConversionUtils.cs +++ b/src/NTwain/Data/SizeAndConversionUtils.cs @@ -1,11 +1,10 @@ using System; using System.Collections.Generic; -namespace NTwain.Data -{ +namespace NTwain.Data; - public static class SizeAndConversionUtils - { +public static class SizeAndConversionUtils +{ /// /// Maps id with its enum /// value type when applicable @@ -15,10 +14,10 @@ namespace NTwain.Data /// public static Type? GetEnumType(CAP cap) { - if (__map.ContainsKey(cap)) return __map[cap]; - return null; + if (__map.ContainsKey(cap)) return __map[cap]; + return null; } - static readonly Dictionary __map = new() + static readonly Dictionary __map = new() { { CAP.ACAP_XFERMECH, typeof(TWSX) }, { CAP.CAP_ALARMS, typeof(TWAL) }, @@ -162,11 +161,11 @@ namespace NTwain.Data /// public static int GetItemTypeSize(this TWTY type) { - if (__sizes.TryGetValue(type, out int size)) - { - return size; - } - return 0; + if (__sizes.TryGetValue(type, out int size)) + { + return size; + } + return 0; } static readonly IDictionary __sizes = new Dictionary { @@ -186,5 +185,4 @@ namespace NTwain.Data // is it fixed 4 bytes or intptr size? {TWTY.HANDLE, IntPtr.Size}, }; - } } diff --git a/src/NTwain/Data/TWAINH.cs b/src/NTwain/Data/TWAINH.cs index 99fe53e..7ca2b9a 100644 --- a/src/NTwain/Data/TWAINH.cs +++ b/src/NTwain/Data/TWAINH.cs @@ -46,422 +46,237 @@ using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; using System.Text; -namespace NTwain.Data +namespace NTwain.Data; + +///// +///// This file contains content gleaned from version 2.4 of the C/C++ H +///// header file released by the TWAIN Working Group. It's organized like that +///// file to make it easier to maintain. +///// +///// Please do not add any code to this module, save for the minimum needed to +///// maintain a particular definition (such as TW_STR32)... +///// +//public partial class TWAIN +//{ +/////////////////////////////////////////////////////////////////////////////// +// TWAIN Version... +/////////////////////////////////////////////////////////////////////////////// +#region Protocol Version... +public enum TWON_PROTOCOL { - ///// - ///// This file contains content gleaned from version 2.4 of the C/C++ H - ///// header file released by the TWAIN Working Group. It's organized like that - ///// file to make it easier to maintain. - ///// - ///// Please do not add any code to this module, save for the minimum needed to - ///// maintain a particular definition (such as TW_STR32)... - ///// - //public partial class TWAIN - //{ - /////////////////////////////////////////////////////////////////////////////// - // TWAIN Version... - /////////////////////////////////////////////////////////////////////////////// - #region Protocol Version... - public enum TWON_PROTOCOL - { - MAJOR = 2, - MINOR = 5 // Changed for Version 2.5 - }; - #endregion + MAJOR = 2, + MINOR = 5 // Changed for Version 2.5 +}; +#endregion - /////////////////////////////////////////////////////////////////////////////// - // Type Definitions... - /////////////////////////////////////////////////////////////////////////////// - #region Type Definitions... +/////////////////////////////////////////////////////////////////////////////// +// Type Definitions... +/////////////////////////////////////////////////////////////////////////////// +#region Type Definitions... - // Follow these rules - /****************************************************************************** +// Follow these rules +/****************************************************************************** - TW_HANDLE...............IntPtr - TW_MEMREF...............IntPtr - TW_UINTPTR..............UIntPtr +TW_HANDLE...............IntPtr +TW_MEMREF...............IntPtr +TW_UINTPTR..............UIntPtr - TW_INT8.................char - TW_INT16................short - TW_INT32................int (was long on Linux 64-bit) +TW_INT8.................char +TW_INT16................short +TW_INT32................int (was long on Linux 64-bit) - TW_UINT8................byte - TW_UINT16...............ushort - TW_UINT32...............uint (was ulong on Linux 64-bit) - TW_BOOL.................ushort +TW_UINT8................byte +TW_UINT16...............ushort +TW_UINT32...............uint (was ulong on Linux 64-bit) +TW_BOOL.................ushort - ******************************************************************************/ +******************************************************************************/ + +/// +/// Our supported platforms... +/// +public enum Platform +{ + UNKNOWN, + WINDOWS, + LINUX, + MACOSX +}; + +/// +/// Our supported processors... +/// +public enum Processor +{ + UNKNOWN, + X86, + X86_64, + MIPS64EL +}; + +/// +/// Used for strings that go up to 32-bytes... +/// +[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)] +public partial struct TW_STR32 +{ + /// + /// We're stuck with this, because marshalling with packed alignment + /// can't handle arrays... + /// + private byte byItem000; private byte byItem001; private byte byItem002; private byte byItem003; + private byte byItem004; private byte byItem005; private byte byItem006; private byte byItem007; + private byte byItem008; private byte byItem009; private byte byItem010; private byte byItem011; + private byte byItem012; private byte byItem013; private byte byItem014; private byte byItem015; + private byte byItem016; private byte byItem017; private byte byItem018; private byte byItem019; + private byte byItem020; private byte byItem021; private byte byItem022; private byte byItem023; + private byte byItem024; private byte byItem025; private byte byItem026; private byte byItem027; + private byte byItem028; private byte byItem029; private byte byItem030; private byte byItem031; + private byte byItem032; private byte byItem033; /// - /// Our supported platforms... + /// The normal get... /// - public enum Platform + /// + /// + public string Get(Encoding? encoding = null) { - UNKNOWN, - WINDOWS, - LINUX, - MACOSX - }; - - /// - /// Our supported processors... - /// - public enum Processor - { - UNKNOWN, - X86, - X86_64, - MIPS64EL - }; - - /// - /// Used for strings that go up to 32-bytes... - /// - [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)] - public partial struct TW_STR32 - { - /// - /// We're stuck with this, because marshalling with packed alignment - /// can't handle arrays... - /// - private byte byItem000; private byte byItem001; private byte byItem002; private byte byItem003; - private byte byItem004; private byte byItem005; private byte byItem006; private byte byItem007; - private byte byItem008; private byte byItem009; private byte byItem010; private byte byItem011; - private byte byItem012; private byte byItem013; private byte byItem014; private byte byItem015; - private byte byItem016; private byte byItem017; private byte byItem018; private byte byItem019; - private byte byItem020; private byte byItem021; private byte byItem022; private byte byItem023; - private byte byItem024; private byte byItem025; private byte byItem026; private byte byItem027; - private byte byItem028; private byte byItem029; private byte byItem030; private byte byItem031; - private byte byItem032; private byte byItem033; - - /// - /// The normal get... - /// - /// - /// - public string Get(Encoding? encoding = null) - { - return (GetValue(true, encoding)); - } - - /// - /// Use this on Mac OS X if you have a call that uses a string - /// that doesn't include the prefix byte... - /// - /// - /// - public string GetNoPrefix(Encoding? encoding = null) - { - return (GetValue(false, encoding)); - } - - /// - /// Get our value... - /// - /// - /// - /// - private string GetValue(bool a_blMayHavePrefix, Encoding? encoding = null) - { - // convert what we have into a byte array - byte[] abyItem = new byte[34]; - abyItem[0] = byItem000; abyItem[1] = byItem001; abyItem[2] = byItem002; abyItem[3] = byItem003; - abyItem[4] = byItem004; abyItem[5] = byItem005; abyItem[6] = byItem006; abyItem[7] = byItem007; - abyItem[8] = byItem008; abyItem[9] = byItem009; abyItem[10] = byItem010; abyItem[11] = byItem011; - abyItem[12] = byItem012; abyItem[13] = byItem013; abyItem[14] = byItem014; abyItem[15] = byItem015; - abyItem[16] = byItem016; abyItem[17] = byItem017; abyItem[18] = byItem018; abyItem[19] = byItem019; - abyItem[20] = byItem020; abyItem[21] = byItem021; abyItem[22] = byItem022; abyItem[23] = byItem023; - abyItem[24] = byItem024; abyItem[25] = byItem025; abyItem[26] = byItem026; abyItem[27] = byItem027; - abyItem[28] = byItem028; abyItem[29] = byItem029; abyItem[30] = byItem030; abyItem[31] = byItem031; - abyItem[32] = byItem032; abyItem[33] = byItem033; - - // Zero anything after the NUL... - bool blNul = false; - for (int ii = 0; ii < abyItem.Length; ii++) - { - if (!blNul && (abyItem[ii] == 0)) - { - blNul = true; - } - else if (blNul) - { - abyItem[ii] = 0; - } - } - - // change encoding of byte array, then convert the bytes array to a string - string sz = Encoding.Unicode.GetString(Encoding.Convert(encoding ?? Language.GetEncoding(), Encoding.Unicode, abyItem)); - - // If the first character is a NUL, then return the empty string... - while ((sz.Length > 0) && (sz[0] == '\0')) - { - sz = sz.Remove(0, 1); - } - - // We have an emptry string... - if (sz.Length == 0) - { - return (""); - } - - // If we're running on a Mac, take off the prefix 'byte'... - if (a_blMayHavePrefix && TWPlatform.IsMacOSX) - { - sz = sz.Remove(0, 1); - } - - // If we detect a NUL, then split around it... - if (sz.IndexOf('\0') >= 0) - { - sz = sz.Split(new char[] { '\0' })[0]; - } - - // All done... - return (sz); - } - - /// - /// The normal set... - /// - /// - /// - /// - public void Set(string a_sz, Encoding? encoding = null) - { - SetValue(a_sz, true, encoding); - } - - /// - /// Use this on Mac OS X if you have a call that uses a string - /// that doesn't include the prefix byte... - /// - /// - /// - /// - public void SetNoPrefix(string a_sz, Encoding? encoding = null) - { - SetValue(a_sz, false, encoding); - } - - /// - /// Set our value... - /// - /// - /// - /// - private void SetValue(string a_sz, bool a_blMayHavePrefix, Encoding? encoding = null) - { - // If we're running on a Mac, tack on the prefix 'byte'... - if (a_sz == null) - { - a_sz = ""; - } - else if (a_blMayHavePrefix && TWPlatform.IsMacOSX) - { - a_sz = (char)a_sz.Length + a_sz; - } - - // Make sure that we're NUL padded... - string sz = a_sz + - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + - "\0\0"; - if (sz.Length > 34) - { - sz = sz.Remove(34); - } - - // convert string to byte array, then change the encoding of the byte array - byte[] abyItem = Encoding.Convert(Encoding.Unicode, encoding ?? Language.GetEncoding(), Encoding.Unicode.GetBytes(sz)); - - // convert byte array to bytes - if (abyItem.Length > 0) - { - byItem000 = abyItem[0]; byItem001 = abyItem[1]; byItem002 = abyItem[2]; byItem003 = abyItem[3]; - byItem004 = abyItem[4]; byItem005 = abyItem[5]; byItem006 = abyItem[6]; byItem007 = abyItem[7]; - byItem008 = abyItem[8]; byItem009 = abyItem[9]; byItem010 = abyItem[10]; byItem011 = abyItem[11]; - byItem012 = abyItem[12]; byItem013 = abyItem[13]; byItem014 = abyItem[14]; byItem015 = abyItem[15]; - byItem016 = abyItem[16]; byItem017 = abyItem[17]; byItem018 = abyItem[18]; byItem019 = abyItem[19]; - byItem020 = abyItem[20]; byItem021 = abyItem[21]; byItem022 = abyItem[22]; byItem023 = abyItem[23]; - byItem024 = abyItem[24]; byItem025 = abyItem[25]; byItem026 = abyItem[26]; byItem027 = abyItem[27]; - byItem028 = abyItem[28]; byItem029 = abyItem[29]; byItem030 = abyItem[30]; byItem031 = abyItem[31]; - byItem032 = abyItem[32]; byItem033 = abyItem[33]; - } - } + return (GetValue(true, encoding)); } /// - /// Used for strings that go up to 64-bytes... + /// Use this on Mac OS X if you have a call that uses a string + /// that doesn't include the prefix byte... /// - [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)] - public partial struct TW_STR64 + /// + /// + public string GetNoPrefix(Encoding? encoding = null) { - /// - /// We're stuck with this, because marshalling with packed alignment - /// can't handle arrays... - /// - private byte byItem000; private byte byItem001; private byte byItem002; private byte byItem003; - private byte byItem004; private byte byItem005; private byte byItem006; private byte byItem007; - private byte byItem008; private byte byItem009; private byte byItem010; private byte byItem011; - private byte byItem012; private byte byItem013; private byte byItem014; private byte byItem015; - private byte byItem016; private byte byItem017; private byte byItem018; private byte byItem019; - private byte byItem020; private byte byItem021; private byte byItem022; private byte byItem023; - private byte byItem024; private byte byItem025; private byte byItem026; private byte byItem027; - private byte byItem028; private byte byItem029; private byte byItem030; private byte byItem031; - private byte byItem032; private byte byItem033; private byte byItem034; private byte byItem035; - private byte byItem036; private byte byItem037; private byte byItem038; private byte byItem039; - private byte byItem040; private byte byItem041; private byte byItem042; private byte byItem043; - private byte byItem044; private byte byItem045; private byte byItem046; private byte byItem047; - private byte byItem048; private byte byItem049; private byte byItem050; private byte byItem051; - private byte byItem052; private byte byItem053; private byte byItem054; private byte byItem055; - private byte byItem056; private byte byItem057; private byte byItem058; private byte byItem059; - private byte byItem060; private byte byItem061; private byte byItem062; private byte byItem063; - private byte byItem064; private byte byItem065; + return (GetValue(false, encoding)); + } - /// - /// The normal get... - /// - /// - /// - public string Get(Encoding? encoding = null) + /// + /// Get our value... + /// + /// + /// + /// + private string GetValue(bool a_blMayHavePrefix, Encoding? encoding = null) + { + // convert what we have into a byte array + byte[] abyItem = new byte[34]; + abyItem[0] = byItem000; abyItem[1] = byItem001; abyItem[2] = byItem002; abyItem[3] = byItem003; + abyItem[4] = byItem004; abyItem[5] = byItem005; abyItem[6] = byItem006; abyItem[7] = byItem007; + abyItem[8] = byItem008; abyItem[9] = byItem009; abyItem[10] = byItem010; abyItem[11] = byItem011; + abyItem[12] = byItem012; abyItem[13] = byItem013; abyItem[14] = byItem014; abyItem[15] = byItem015; + abyItem[16] = byItem016; abyItem[17] = byItem017; abyItem[18] = byItem018; abyItem[19] = byItem019; + abyItem[20] = byItem020; abyItem[21] = byItem021; abyItem[22] = byItem022; abyItem[23] = byItem023; + abyItem[24] = byItem024; abyItem[25] = byItem025; abyItem[26] = byItem026; abyItem[27] = byItem027; + abyItem[28] = byItem028; abyItem[29] = byItem029; abyItem[30] = byItem030; abyItem[31] = byItem031; + abyItem[32] = byItem032; abyItem[33] = byItem033; + + // Zero anything after the NUL... + bool blNul = false; + for (int ii = 0; ii < abyItem.Length; ii++) { - return (GetValue(true, encoding)); + if (!blNul && (abyItem[ii] == 0)) + { + blNul = true; + } + else if (blNul) + { + abyItem[ii] = 0; + } } - /// - /// Use this on Mac OS X if you have a call that uses a string - /// that doesn't include the prefix byte... - /// - /// - /// - public string GetNoPrefix(Encoding? encoding = null) + // change encoding of byte array, then convert the bytes array to a string + string sz = Encoding.Unicode.GetString(Encoding.Convert(encoding ?? Language.GetEncoding(), Encoding.Unicode, abyItem)); + + // If the first character is a NUL, then return the empty string... + while ((sz.Length > 0) && (sz[0] == '\0')) { - return (GetValue(false, encoding)); + sz = sz.Remove(0, 1); } - /// - /// Get our value... - /// - /// - /// - /// - private string GetValue(bool a_blMayHavePrefix, Encoding? encoding = null) + // We have an emptry string... + if (sz.Length == 0) { - // convert what we have into a byte array - byte[] abyItem = new byte[66]; - abyItem[0] = byItem000; abyItem[1] = byItem001; abyItem[2] = byItem002; abyItem[3] = byItem003; - abyItem[4] = byItem004; abyItem[5] = byItem005; abyItem[6] = byItem006; abyItem[7] = byItem007; - abyItem[8] = byItem008; abyItem[9] = byItem009; abyItem[10] = byItem010; abyItem[11] = byItem011; - abyItem[12] = byItem012; abyItem[13] = byItem013; abyItem[14] = byItem014; abyItem[15] = byItem015; - abyItem[16] = byItem016; abyItem[17] = byItem017; abyItem[18] = byItem018; abyItem[19] = byItem019; - abyItem[20] = byItem020; abyItem[21] = byItem021; abyItem[22] = byItem022; abyItem[23] = byItem023; - abyItem[24] = byItem024; abyItem[25] = byItem025; abyItem[26] = byItem026; abyItem[27] = byItem027; - abyItem[28] = byItem028; abyItem[29] = byItem029; abyItem[30] = byItem030; abyItem[31] = byItem031; - abyItem[32] = byItem032; abyItem[33] = byItem033; abyItem[34] = byItem034; abyItem[35] = byItem035; - abyItem[36] = byItem036; abyItem[37] = byItem037; abyItem[38] = byItem038; abyItem[39] = byItem039; - abyItem[40] = byItem040; abyItem[41] = byItem041; abyItem[42] = byItem042; abyItem[43] = byItem043; - abyItem[44] = byItem044; abyItem[45] = byItem045; abyItem[46] = byItem046; abyItem[47] = byItem047; - abyItem[48] = byItem048; abyItem[49] = byItem049; abyItem[50] = byItem050; abyItem[51] = byItem051; - abyItem[52] = byItem052; abyItem[53] = byItem053; abyItem[54] = byItem054; abyItem[55] = byItem055; - abyItem[56] = byItem056; abyItem[57] = byItem057; abyItem[58] = byItem058; abyItem[59] = byItem059; - abyItem[60] = byItem060; abyItem[61] = byItem061; abyItem[62] = byItem062; abyItem[63] = byItem063; - abyItem[64] = byItem064; abyItem[65] = byItem065; - - // Zero anything after the NUL... - bool blNul = false; - for (int ii = 0; ii < abyItem.Length; ii++) - { - if (!blNul && (abyItem[ii] == 0)) - { - blNul = true; - } - else if (blNul) - { - abyItem[ii] = 0; - } - } - - // change encoding of byte array, then convert the bytes array to a string - string sz = Encoding.Unicode.GetString(Encoding.Convert(encoding ?? Language.GetEncoding(), Encoding.Unicode, abyItem)); - - // If the first character is a NUL, then return the empty string... - if (sz[0] == '\0') - { - return (""); - } - - // If we're running on a Mac, take off the prefix 'byte'... - if (a_blMayHavePrefix && TWPlatform.IsMacOSX) - { - sz = sz.Remove(0, 1); - } - - // If we detect a NUL, then split around it... - if (sz.IndexOf('\0') >= 0) - { - sz = sz.Split(new char[] { '\0' })[0]; - } - - // All done... - return (sz); + return (""); } - /// - /// The normal set... - /// - /// - /// - /// - public void Set(string a_sz, Encoding? encoding = null) + // If we're running on a Mac, take off the prefix 'byte'... + if (a_blMayHavePrefix && TWPlatform.IsMacOSX) { - SetValue(a_sz, true, encoding); + sz = sz.Remove(0, 1); } - /// - /// Use this on Mac OS X if you have a call that uses a string - /// that doesn't include the prefix byte... - /// - /// - /// - /// - public void SetNoPrefix(string a_sz, Encoding? encoding = null) + // If we detect a NUL, then split around it... + if (sz.IndexOf('\0') >= 0) { - SetValue(a_sz, false, encoding); + sz = sz.Split(new char[] { '\0' })[0]; } - /// - /// Set our value... - /// - /// - /// - /// - private void SetValue(string a_sz, bool a_blMayHavePrefix, Encoding? encoding = null) + // All done... + return (sz); + } + + /// + /// The normal set... + /// + /// + /// + /// + public void Set(string a_sz, Encoding? encoding = null) + { + SetValue(a_sz, true, encoding); + } + + /// + /// Use this on Mac OS X if you have a call that uses a string + /// that doesn't include the prefix byte... + /// + /// + /// + /// + public void SetNoPrefix(string a_sz, Encoding? encoding = null) + { + SetValue(a_sz, false, encoding); + } + + /// + /// Set our value... + /// + /// + /// + /// + private void SetValue(string a_sz, bool a_blMayHavePrefix, Encoding? encoding = null) + { + // If we're running on a Mac, tack on the prefix 'byte'... + if (a_sz == null) { - // If we're running on a Mac, tack on the prefix 'byte'... - if (a_sz == null) - { - a_sz = ""; - } - else if (a_blMayHavePrefix && TWPlatform.IsMacOSX) - { - a_sz = (char)a_sz.Length + a_sz; - } + a_sz = ""; + } + else if (a_blMayHavePrefix && TWPlatform.IsMacOSX) + { + a_sz = (char)a_sz.Length + a_sz; + } - // Make sure that we're NUL padded... - string sz = - a_sz + - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + - "\0\0"; - if (sz.Length > 66) - { - sz = sz.Remove(66); - } + // Make sure that we're NUL padded... + string sz = a_sz + + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + + "\0\0"; + if (sz.Length > 34) + { + sz = sz.Remove(34); + } - // convert string to byte array, then change the encoding of the byte array - byte[] abyItem = Encoding.Convert(Encoding.Unicode, encoding ?? Language.GetEncoding(), Encoding.Unicode.GetBytes(sz)); + // convert string to byte array, then change the encoding of the byte array + byte[] abyItem = Encoding.Convert(Encoding.Unicode, encoding ?? Language.GetEncoding(), Encoding.Unicode.GetBytes(sz)); - // concert byte array to bytes + // convert byte array to bytes + if (abyItem.Length > 0) + { byItem000 = abyItem[0]; byItem001 = abyItem[1]; byItem002 = abyItem[2]; byItem003 = abyItem[3]; byItem004 = abyItem[4]; byItem005 = abyItem[5]; byItem006 = abyItem[6]; byItem007 = abyItem[7]; byItem008 = abyItem[8]; byItem009 = abyItem[9]; byItem010 = abyItem[10]; byItem011 = abyItem[11]; @@ -470,4167 +285,4351 @@ namespace NTwain.Data byItem020 = abyItem[20]; byItem021 = abyItem[21]; byItem022 = abyItem[22]; byItem023 = abyItem[23]; byItem024 = abyItem[24]; byItem025 = abyItem[25]; byItem026 = abyItem[26]; byItem027 = abyItem[27]; byItem028 = abyItem[28]; byItem029 = abyItem[29]; byItem030 = abyItem[30]; byItem031 = abyItem[31]; - byItem032 = abyItem[32]; byItem033 = abyItem[33]; byItem034 = abyItem[34]; byItem035 = abyItem[35]; - byItem036 = abyItem[36]; byItem037 = abyItem[37]; byItem038 = abyItem[38]; byItem039 = abyItem[39]; - byItem040 = abyItem[40]; byItem041 = abyItem[41]; byItem042 = abyItem[42]; byItem043 = abyItem[43]; - byItem044 = abyItem[44]; byItem045 = abyItem[45]; byItem046 = abyItem[46]; byItem047 = abyItem[47]; - byItem048 = abyItem[48]; byItem049 = abyItem[49]; byItem050 = abyItem[50]; byItem051 = abyItem[51]; - byItem052 = abyItem[52]; byItem053 = abyItem[53]; byItem054 = abyItem[54]; byItem055 = abyItem[55]; - byItem056 = abyItem[56]; byItem057 = abyItem[57]; byItem058 = abyItem[58]; byItem059 = abyItem[59]; - byItem060 = abyItem[60]; byItem061 = abyItem[61]; byItem062 = abyItem[62]; byItem063 = abyItem[63]; - byItem064 = abyItem[64]; byItem065 = abyItem[65]; + byItem032 = abyItem[32]; byItem033 = abyItem[33]; } } - - /// - /// Used for strings that go up to 128-bytes... - /// - [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)] - public partial struct TW_STR128 - { - /// - /// We're stuck with this, because marshalling with packed alignment - /// can't handle arrays... - /// - private byte byItem000; private byte byItem001; private byte byItem002; private byte byItem003; - private byte byItem004; private byte byItem005; private byte byItem006; private byte byItem007; - private byte byItem008; private byte byItem009; private byte byItem010; private byte byItem011; - private byte byItem012; private byte byItem013; private byte byItem014; private byte byItem015; - private byte byItem016; private byte byItem017; private byte byItem018; private byte byItem019; - private byte byItem020; private byte byItem021; private byte byItem022; private byte byItem023; - private byte byItem024; private byte byItem025; private byte byItem026; private byte byItem027; - private byte byItem028; private byte byItem029; private byte byItem030; private byte byItem031; - private byte byItem032; private byte byItem033; private byte byItem034; private byte byItem035; - private byte byItem036; private byte byItem037; private byte byItem038; private byte byItem039; - private byte byItem040; private byte byItem041; private byte byItem042; private byte byItem043; - private byte byItem044; private byte byItem045; private byte byItem046; private byte byItem047; - private byte byItem048; private byte byItem049; private byte byItem050; private byte byItem051; - private byte byItem052; private byte byItem053; private byte byItem054; private byte byItem055; - private byte byItem056; private byte byItem057; private byte byItem058; private byte byItem059; - private byte byItem060; private byte byItem061; private byte byItem062; private byte byItem063; - private byte byItem064; private byte byItem065; private byte byItem066; private byte byItem067; - private byte byItem068; private byte byItem069; private byte byItem070; private byte byItem071; - private byte byItem072; private byte byItem073; private byte byItem074; private byte byItem075; - private byte byItem076; private byte byItem077; private byte byItem078; private byte byItem079; - private byte byItem080; private byte byItem081; private byte byItem082; private byte byItem083; - private byte byItem084; private byte byItem085; private byte byItem086; private byte byItem087; - private byte byItem088; private byte byItem089; private byte byItem090; private byte byItem091; - private byte byItem092; private byte byItem093; private byte byItem094; private byte byItem095; - private byte byItem096; private byte byItem097; private byte byItem098; private byte byItem099; - private byte byItem100; private byte byItem101; private byte byItem102; private byte byItem103; - private byte byItem104; private byte byItem105; private byte byItem106; private byte byItem107; - private byte byItem108; private byte byItem109; private byte byItem110; private byte byItem111; - private byte byItem112; private byte byItem113; private byte byItem114; private byte byItem115; - private byte byItem116; private byte byItem117; private byte byItem118; private byte byItem119; - private byte byItem120; private byte byItem121; private byte byItem122; private byte byItem123; - private byte byItem124; private byte byItem125; private byte byItem126; private byte byItem127; - private byte byItem128; private byte byItem129; - - /// - /// The normal get... - /// - /// - /// - public string Get(Encoding? encoding = null) - { - return (GetValue(true, encoding)); - } - - /// - /// Use this on Mac OS X if you have a call that uses a string - /// that doesn't include the prefix byte... - /// - /// - /// - public string GetNoPrefix(Encoding? encoding = null) - { - return (GetValue(false, encoding)); - } - - /// - /// Get our value... - /// - /// - /// - /// - private string GetValue(bool a_blMayHavePrefix, Encoding? encoding = null) - { - // convert what we have into a byte array - byte[] abyItem = new byte[130]; - abyItem[0] = byItem000; abyItem[1] = byItem001; abyItem[2] = byItem002; abyItem[3] = byItem003; - abyItem[4] = byItem004; abyItem[5] = byItem005; abyItem[6] = byItem006; abyItem[7] = byItem007; - abyItem[8] = byItem008; abyItem[9] = byItem009; abyItem[10] = byItem010; abyItem[11] = byItem011; - abyItem[12] = byItem012; abyItem[13] = byItem013; abyItem[14] = byItem014; abyItem[15] = byItem015; - abyItem[16] = byItem016; abyItem[17] = byItem017; abyItem[18] = byItem018; abyItem[19] = byItem019; - abyItem[20] = byItem020; abyItem[21] = byItem021; abyItem[22] = byItem022; abyItem[23] = byItem023; - abyItem[24] = byItem024; abyItem[25] = byItem025; abyItem[26] = byItem026; abyItem[27] = byItem027; - abyItem[28] = byItem028; abyItem[29] = byItem029; abyItem[30] = byItem030; abyItem[31] = byItem031; - abyItem[32] = byItem032; abyItem[33] = byItem033; abyItem[34] = byItem034; abyItem[35] = byItem035; - abyItem[36] = byItem036; abyItem[37] = byItem037; abyItem[38] = byItem038; abyItem[39] = byItem039; - abyItem[40] = byItem040; abyItem[41] = byItem041; abyItem[42] = byItem042; abyItem[43] = byItem043; - abyItem[44] = byItem044; abyItem[45] = byItem045; abyItem[46] = byItem046; abyItem[47] = byItem047; - abyItem[48] = byItem048; abyItem[49] = byItem049; abyItem[50] = byItem050; abyItem[51] = byItem051; - abyItem[52] = byItem052; abyItem[53] = byItem053; abyItem[54] = byItem054; abyItem[55] = byItem055; - abyItem[56] = byItem056; abyItem[57] = byItem057; abyItem[58] = byItem058; abyItem[59] = byItem059; - abyItem[60] = byItem060; abyItem[61] = byItem061; abyItem[62] = byItem062; abyItem[63] = byItem063; - abyItem[64] = byItem064; abyItem[65] = byItem065; abyItem[66] = byItem066; abyItem[67] = byItem067; - abyItem[68] = byItem068; abyItem[69] = byItem069; abyItem[70] = byItem070; abyItem[71] = byItem071; - abyItem[72] = byItem072; abyItem[73] = byItem073; abyItem[74] = byItem074; abyItem[75] = byItem075; - abyItem[76] = byItem076; abyItem[77] = byItem077; abyItem[78] = byItem078; abyItem[79] = byItem079; - abyItem[80] = byItem080; abyItem[81] = byItem081; abyItem[82] = byItem082; abyItem[83] = byItem083; - abyItem[84] = byItem084; abyItem[85] = byItem085; abyItem[86] = byItem086; abyItem[87] = byItem087; - abyItem[88] = byItem088; abyItem[89] = byItem089; abyItem[90] = byItem090; abyItem[91] = byItem091; - abyItem[92] = byItem092; abyItem[93] = byItem093; abyItem[94] = byItem094; abyItem[95] = byItem095; - abyItem[96] = byItem096; abyItem[97] = byItem097; abyItem[98] = byItem098; abyItem[99] = byItem099; - abyItem[100] = byItem100; abyItem[101] = byItem101; abyItem[102] = byItem102; abyItem[103] = byItem103; - abyItem[104] = byItem104; abyItem[105] = byItem105; abyItem[106] = byItem106; abyItem[107] = byItem107; - abyItem[108] = byItem108; abyItem[109] = byItem109; abyItem[110] = byItem110; abyItem[111] = byItem111; - abyItem[112] = byItem112; abyItem[113] = byItem113; abyItem[114] = byItem114; abyItem[115] = byItem115; - abyItem[116] = byItem116; abyItem[117] = byItem117; abyItem[118] = byItem118; abyItem[119] = byItem119; - abyItem[120] = byItem120; abyItem[121] = byItem121; abyItem[122] = byItem122; abyItem[123] = byItem123; - abyItem[124] = byItem124; abyItem[125] = byItem125; abyItem[126] = byItem126; abyItem[127] = byItem127; - abyItem[128] = byItem128; abyItem[129] = byItem129; - - // Zero anything after the NUL... - bool blNul = false; - for (int ii = 0; ii < abyItem.Length; ii++) - { - if (!blNul && (abyItem[ii] == 0)) - { - blNul = true; - } - else if (blNul) - { - abyItem[ii] = 0; - } - } - - // change encoding of byte array, then convert the bytes array to a string - string sz = Encoding.Unicode.GetString(Encoding.Convert(encoding ?? Language.GetEncoding(), Encoding.Unicode, abyItem)); - - // If the first character is a NUL, then return the empty string... - if (sz[0] == '\0') - { - return (""); - } - - // If we're running on a Mac, take off the prefix 'byte'... - if (a_blMayHavePrefix && TWPlatform.IsMacOSX) - { - sz = sz.Remove(0, 1); - } - - // If we detect a NUL, then split around it... - if (sz.IndexOf('\0') >= 0) - { - sz = sz.Split(new char[] { '\0' })[0]; - } - - // All done... - return (sz); - } - - /// - /// The normal set... - /// - /// - /// - /// - public void Set(string a_sz, Encoding? encoding = null) - { - SetValue(a_sz, true, encoding); - } - - /// - /// Use this on Mac OS X if you have a call that uses a string - /// that doesn't include the prefix byte... - /// - /// - /// - /// - public void SetNoPrefix(string a_sz, Encoding? encoding = null) - { - SetValue(a_sz, false, encoding); - } - - /// - /// Set our value... - /// - /// - /// - /// - private void SetValue(string a_sz, bool a_blMayHavePrefix, Encoding? encoding = null) - { - // If we're running on a Mac, tack on the prefix 'byte'... - if (a_sz == null) - { - a_sz = ""; - } - else if (a_blMayHavePrefix && TWPlatform.IsMacOSX) - { - a_sz = (char)a_sz.Length + a_sz; - } - - // Make sure that we're NUL padded... - string sz = - a_sz + - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + - "\0\0"; - if (sz.Length > 130) - { - sz = sz.Remove(130); - } - - // convert string to byte array, then change the encoding of the byte array - byte[] abyItem = Encoding.Convert(Encoding.Unicode, encoding ?? Language.GetEncoding(), Encoding.Unicode.GetBytes(sz)); - - // concert byte array to bytes - byItem000 = abyItem[0]; byItem001 = abyItem[1]; byItem002 = abyItem[2]; byItem003 = abyItem[3]; - byItem004 = abyItem[4]; byItem005 = abyItem[5]; byItem006 = abyItem[6]; byItem007 = abyItem[7]; - byItem008 = abyItem[8]; byItem009 = abyItem[9]; byItem010 = abyItem[10]; byItem011 = abyItem[11]; - byItem012 = abyItem[12]; byItem013 = abyItem[13]; byItem014 = abyItem[14]; byItem015 = abyItem[15]; - byItem016 = abyItem[16]; byItem017 = abyItem[17]; byItem018 = abyItem[18]; byItem019 = abyItem[19]; - byItem020 = abyItem[20]; byItem021 = abyItem[21]; byItem022 = abyItem[22]; byItem023 = abyItem[23]; - byItem024 = abyItem[24]; byItem025 = abyItem[25]; byItem026 = abyItem[26]; byItem027 = abyItem[27]; - byItem028 = abyItem[28]; byItem029 = abyItem[29]; byItem030 = abyItem[30]; byItem031 = abyItem[31]; - byItem032 = abyItem[32]; byItem033 = abyItem[33]; byItem034 = abyItem[34]; byItem035 = abyItem[35]; - byItem036 = abyItem[36]; byItem037 = abyItem[37]; byItem038 = abyItem[38]; byItem039 = abyItem[39]; - byItem040 = abyItem[40]; byItem041 = abyItem[41]; byItem042 = abyItem[42]; byItem043 = abyItem[43]; - byItem044 = abyItem[44]; byItem045 = abyItem[45]; byItem046 = abyItem[46]; byItem047 = abyItem[47]; - byItem048 = abyItem[48]; byItem049 = abyItem[49]; byItem050 = abyItem[50]; byItem051 = abyItem[51]; - byItem052 = abyItem[52]; byItem053 = abyItem[53]; byItem054 = abyItem[54]; byItem055 = abyItem[55]; - byItem056 = abyItem[56]; byItem057 = abyItem[57]; byItem058 = abyItem[58]; byItem059 = abyItem[59]; - byItem060 = abyItem[60]; byItem061 = abyItem[61]; byItem062 = abyItem[62]; byItem063 = abyItem[63]; - byItem064 = abyItem[64]; byItem065 = abyItem[65]; byItem066 = abyItem[66]; byItem067 = abyItem[67]; - byItem068 = abyItem[68]; byItem069 = abyItem[69]; byItem070 = abyItem[70]; byItem071 = abyItem[71]; - byItem072 = abyItem[72]; byItem073 = abyItem[73]; byItem074 = abyItem[74]; byItem075 = abyItem[75]; - byItem076 = abyItem[76]; byItem077 = abyItem[77]; byItem078 = abyItem[78]; byItem079 = abyItem[79]; - byItem080 = abyItem[80]; byItem081 = abyItem[81]; byItem082 = abyItem[82]; byItem083 = abyItem[83]; - byItem084 = abyItem[84]; byItem085 = abyItem[85]; byItem086 = abyItem[86]; byItem087 = abyItem[87]; - byItem088 = abyItem[88]; byItem089 = abyItem[89]; byItem090 = abyItem[90]; byItem091 = abyItem[91]; - byItem092 = abyItem[92]; byItem093 = abyItem[93]; byItem094 = abyItem[94]; byItem095 = abyItem[95]; - byItem096 = abyItem[96]; byItem097 = abyItem[97]; byItem098 = abyItem[98]; byItem099 = abyItem[99]; - byItem100 = abyItem[100]; byItem101 = abyItem[101]; byItem102 = abyItem[102]; byItem103 = abyItem[103]; - byItem104 = abyItem[104]; byItem105 = abyItem[105]; byItem106 = abyItem[106]; byItem107 = abyItem[107]; - byItem108 = abyItem[108]; byItem109 = abyItem[109]; byItem110 = abyItem[110]; byItem111 = abyItem[111]; - byItem112 = abyItem[112]; byItem113 = abyItem[113]; byItem114 = abyItem[114]; byItem115 = abyItem[115]; - byItem116 = abyItem[116]; byItem117 = abyItem[117]; byItem118 = abyItem[118]; byItem119 = abyItem[119]; - byItem120 = abyItem[120]; byItem121 = abyItem[121]; byItem122 = abyItem[122]; byItem123 = abyItem[123]; - byItem124 = abyItem[124]; byItem125 = abyItem[125]; byItem126 = abyItem[126]; byItem127 = abyItem[127]; - byItem128 = abyItem[128]; byItem129 = abyItem[129]; - } - } - - /// - /// Used for strings that go up to 256-bytes... - /// - [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)] - public partial struct TW_STR255 - { - /// - /// We're stuck with this, because marshalling with packed alignment - /// can't handle arrays... - /// - private byte byItem000; private byte byItem001; private byte byItem002; private byte byItem003; - private byte byItem004; private byte byItem005; private byte byItem006; private byte byItem007; - private byte byItem008; private byte byItem009; private byte byItem010; private byte byItem011; - private byte byItem012; private byte byItem013; private byte byItem014; private byte byItem015; - private byte byItem016; private byte byItem017; private byte byItem018; private byte byItem019; - private byte byItem020; private byte byItem021; private byte byItem022; private byte byItem023; - private byte byItem024; private byte byItem025; private byte byItem026; private byte byItem027; - private byte byItem028; private byte byItem029; private byte byItem030; private byte byItem031; - private byte byItem032; private byte byItem033; private byte byItem034; private byte byItem035; - private byte byItem036; private byte byItem037; private byte byItem038; private byte byItem039; - private byte byItem040; private byte byItem041; private byte byItem042; private byte byItem043; - private byte byItem044; private byte byItem045; private byte byItem046; private byte byItem047; - private byte byItem048; private byte byItem049; private byte byItem050; private byte byItem051; - private byte byItem052; private byte byItem053; private byte byItem054; private byte byItem055; - private byte byItem056; private byte byItem057; private byte byItem058; private byte byItem059; - private byte byItem060; private byte byItem061; private byte byItem062; private byte byItem063; - private byte byItem064; private byte byItem065; private byte byItem066; private byte byItem067; - private byte byItem068; private byte byItem069; private byte byItem070; private byte byItem071; - private byte byItem072; private byte byItem073; private byte byItem074; private byte byItem075; - private byte byItem076; private byte byItem077; private byte byItem078; private byte byItem079; - private byte byItem080; private byte byItem081; private byte byItem082; private byte byItem083; - private byte byItem084; private byte byItem085; private byte byItem086; private byte byItem087; - private byte byItem088; private byte byItem089; private byte byItem090; private byte byItem091; - private byte byItem092; private byte byItem093; private byte byItem094; private byte byItem095; - private byte byItem096; private byte byItem097; private byte byItem098; private byte byItem099; - private byte byItem100; private byte byItem101; private byte byItem102; private byte byItem103; - private byte byItem104; private byte byItem105; private byte byItem106; private byte byItem107; - private byte byItem108; private byte byItem109; private byte byItem110; private byte byItem111; - private byte byItem112; private byte byItem113; private byte byItem114; private byte byItem115; - private byte byItem116; private byte byItem117; private byte byItem118; private byte byItem119; - private byte byItem120; private byte byItem121; private byte byItem122; private byte byItem123; - private byte byItem124; private byte byItem125; private byte byItem126; private byte byItem127; - private byte byItem128; private byte byItem129; private byte byItem130; private byte byItem131; - private byte byItem132; private byte byItem133; private byte byItem134; private byte byItem135; - private byte byItem136; private byte byItem137; private byte byItem138; private byte byItem139; - private byte byItem140; private byte byItem141; private byte byItem142; private byte byItem143; - private byte byItem144; private byte byItem145; private byte byItem146; private byte byItem147; - private byte byItem148; private byte byItem149; private byte byItem150; private byte byItem151; - private byte byItem152; private byte byItem153; private byte byItem154; private byte byItem155; - private byte byItem156; private byte byItem157; private byte byItem158; private byte byItem159; - private byte byItem160; private byte byItem161; private byte byItem162; private byte byItem163; - private byte byItem164; private byte byItem165; private byte byItem166; private byte byItem167; - private byte byItem168; private byte byItem169; private byte byItem170; private byte byItem171; - private byte byItem172; private byte byItem173; private byte byItem174; private byte byItem175; - private byte byItem176; private byte byItem177; private byte byItem178; private byte byItem179; - private byte byItem180; private byte byItem181; private byte byItem182; private byte byItem183; - private byte byItem184; private byte byItem185; private byte byItem186; private byte byItem187; - private byte byItem188; private byte byItem189; private byte byItem190; private byte byItem191; - private byte byItem192; private byte byItem193; private byte byItem194; private byte byItem195; - private byte byItem196; private byte byItem197; private byte byItem198; private byte byItem199; - private byte byItem200; private byte byItem201; private byte byItem202; private byte byItem203; - private byte byItem204; private byte byItem205; private byte byItem206; private byte byItem207; - private byte byItem208; private byte byItem209; private byte byItem210; private byte byItem211; - private byte byItem212; private byte byItem213; private byte byItem214; private byte byItem215; - private byte byItem216; private byte byItem217; private byte byItem218; private byte byItem219; - private byte byItem220; private byte byItem221; private byte byItem222; private byte byItem223; - private byte byItem224; private byte byItem225; private byte byItem226; private byte byItem227; - private byte byItem228; private byte byItem229; private byte byItem230; private byte byItem231; - private byte byItem232; private byte byItem233; private byte byItem234; private byte byItem235; - private byte byItem236; private byte byItem237; private byte byItem238; private byte byItem239; - private byte byItem240; private byte byItem241; private byte byItem242; private byte byItem243; - private byte byItem244; private byte byItem245; private byte byItem246; private byte byItem247; - private byte byItem248; private byte byItem249; private byte byItem250; private byte byItem251; - private byte byItem252; private byte byItem253; private byte byItem254; private byte byItem255; - - /// - /// The normal get... - /// - /// - /// - public string Get(Encoding? encoding = null) - { - return (GetValue(true, encoding)); - } - - /// - /// Use this on Mac OS X if you have a call that uses a string - /// that doesn't include the prefix byte... - /// - /// - /// - public string GetNoPrefix(Encoding? encoding = null) - { - return (GetValue(false, encoding)); - } - - /// - /// Get our value... - /// - /// - /// - /// - private string GetValue(bool a_blMayHavePrefix, Encoding? encoding = null) - { - // convert what we have into a byte array - byte[] abyItem = new byte[256]; - abyItem[0] = byItem000; abyItem[1] = byItem001; abyItem[2] = byItem002; abyItem[3] = byItem003; - abyItem[4] = byItem004; abyItem[5] = byItem005; abyItem[6] = byItem006; abyItem[7] = byItem007; - abyItem[8] = byItem008; abyItem[9] = byItem009; abyItem[10] = byItem010; abyItem[11] = byItem011; - abyItem[12] = byItem012; abyItem[13] = byItem013; abyItem[14] = byItem014; abyItem[15] = byItem015; - abyItem[16] = byItem016; abyItem[17] = byItem017; abyItem[18] = byItem018; abyItem[19] = byItem019; - abyItem[20] = byItem020; abyItem[21] = byItem021; abyItem[22] = byItem022; abyItem[23] = byItem023; - abyItem[24] = byItem024; abyItem[25] = byItem025; abyItem[26] = byItem026; abyItem[27] = byItem027; - abyItem[28] = byItem028; abyItem[29] = byItem029; abyItem[30] = byItem030; abyItem[31] = byItem031; - abyItem[32] = byItem032; abyItem[33] = byItem033; abyItem[34] = byItem034; abyItem[35] = byItem035; - abyItem[36] = byItem036; abyItem[37] = byItem037; abyItem[38] = byItem038; abyItem[39] = byItem039; - abyItem[40] = byItem040; abyItem[41] = byItem041; abyItem[42] = byItem042; abyItem[43] = byItem043; - abyItem[44] = byItem044; abyItem[45] = byItem045; abyItem[46] = byItem046; abyItem[47] = byItem047; - abyItem[48] = byItem048; abyItem[49] = byItem049; abyItem[50] = byItem050; abyItem[51] = byItem051; - abyItem[52] = byItem052; abyItem[53] = byItem053; abyItem[54] = byItem054; abyItem[55] = byItem055; - abyItem[56] = byItem056; abyItem[57] = byItem057; abyItem[58] = byItem058; abyItem[59] = byItem059; - abyItem[60] = byItem060; abyItem[61] = byItem061; abyItem[62] = byItem062; abyItem[63] = byItem063; - abyItem[64] = byItem064; abyItem[65] = byItem065; abyItem[66] = byItem066; abyItem[67] = byItem067; - abyItem[68] = byItem068; abyItem[69] = byItem069; abyItem[70] = byItem070; abyItem[71] = byItem071; - abyItem[72] = byItem072; abyItem[73] = byItem073; abyItem[74] = byItem074; abyItem[75] = byItem075; - abyItem[76] = byItem076; abyItem[77] = byItem077; abyItem[78] = byItem078; abyItem[79] = byItem079; - abyItem[80] = byItem080; abyItem[81] = byItem081; abyItem[82] = byItem082; abyItem[83] = byItem083; - abyItem[84] = byItem084; abyItem[85] = byItem085; abyItem[86] = byItem086; abyItem[87] = byItem087; - abyItem[88] = byItem088; abyItem[89] = byItem089; abyItem[90] = byItem090; abyItem[91] = byItem091; - abyItem[92] = byItem092; abyItem[93] = byItem093; abyItem[94] = byItem094; abyItem[95] = byItem095; - abyItem[96] = byItem096; abyItem[97] = byItem097; abyItem[98] = byItem098; abyItem[99] = byItem099; - abyItem[100] = byItem100; abyItem[101] = byItem101; abyItem[102] = byItem102; abyItem[103] = byItem103; - abyItem[104] = byItem104; abyItem[105] = byItem105; abyItem[106] = byItem106; abyItem[107] = byItem107; - abyItem[108] = byItem108; abyItem[109] = byItem109; abyItem[110] = byItem110; abyItem[111] = byItem111; - abyItem[112] = byItem112; abyItem[113] = byItem113; abyItem[114] = byItem114; abyItem[115] = byItem115; - abyItem[116] = byItem116; abyItem[117] = byItem117; abyItem[118] = byItem118; abyItem[119] = byItem119; - abyItem[120] = byItem120; abyItem[121] = byItem121; abyItem[122] = byItem122; abyItem[123] = byItem123; - abyItem[124] = byItem124; abyItem[125] = byItem125; abyItem[126] = byItem126; abyItem[127] = byItem127; - abyItem[128] = byItem128; abyItem[129] = byItem129; abyItem[130] = byItem130; abyItem[131] = byItem131; - abyItem[132] = byItem132; abyItem[133] = byItem133; abyItem[134] = byItem134; abyItem[135] = byItem135; - abyItem[136] = byItem136; abyItem[137] = byItem137; abyItem[138] = byItem138; abyItem[139] = byItem139; - abyItem[140] = byItem140; abyItem[141] = byItem141; abyItem[142] = byItem142; abyItem[143] = byItem143; - abyItem[144] = byItem144; abyItem[145] = byItem145; abyItem[146] = byItem146; abyItem[147] = byItem147; - abyItem[148] = byItem148; abyItem[149] = byItem149; abyItem[150] = byItem150; abyItem[151] = byItem151; - abyItem[152] = byItem152; abyItem[153] = byItem153; abyItem[154] = byItem154; abyItem[155] = byItem155; - abyItem[156] = byItem156; abyItem[157] = byItem157; abyItem[158] = byItem158; abyItem[159] = byItem159; - abyItem[160] = byItem160; abyItem[161] = byItem161; abyItem[162] = byItem162; abyItem[163] = byItem163; - abyItem[164] = byItem164; abyItem[165] = byItem165; abyItem[166] = byItem166; abyItem[167] = byItem167; - abyItem[168] = byItem168; abyItem[169] = byItem169; abyItem[170] = byItem170; abyItem[171] = byItem171; - abyItem[172] = byItem172; abyItem[173] = byItem173; abyItem[174] = byItem174; abyItem[175] = byItem175; - abyItem[176] = byItem176; abyItem[177] = byItem177; abyItem[178] = byItem178; abyItem[179] = byItem179; - abyItem[180] = byItem180; abyItem[181] = byItem181; abyItem[182] = byItem182; abyItem[183] = byItem183; - abyItem[184] = byItem184; abyItem[185] = byItem185; abyItem[186] = byItem186; abyItem[187] = byItem187; - abyItem[188] = byItem188; abyItem[189] = byItem189; abyItem[190] = byItem190; abyItem[191] = byItem191; - abyItem[192] = byItem192; abyItem[193] = byItem193; abyItem[194] = byItem194; abyItem[195] = byItem195; - abyItem[196] = byItem196; abyItem[197] = byItem197; abyItem[198] = byItem198; abyItem[199] = byItem199; - abyItem[200] = byItem200; abyItem[201] = byItem201; abyItem[202] = byItem202; abyItem[203] = byItem203; - abyItem[204] = byItem204; abyItem[205] = byItem205; abyItem[206] = byItem206; abyItem[207] = byItem207; - abyItem[208] = byItem208; abyItem[209] = byItem209; abyItem[210] = byItem210; abyItem[211] = byItem211; - abyItem[212] = byItem212; abyItem[213] = byItem213; abyItem[214] = byItem214; abyItem[215] = byItem215; - abyItem[216] = byItem216; abyItem[217] = byItem217; abyItem[218] = byItem218; abyItem[219] = byItem219; - abyItem[220] = byItem220; abyItem[221] = byItem221; abyItem[222] = byItem222; abyItem[223] = byItem223; - abyItem[224] = byItem224; abyItem[225] = byItem225; abyItem[226] = byItem226; abyItem[227] = byItem227; - abyItem[228] = byItem228; abyItem[229] = byItem229; abyItem[230] = byItem230; abyItem[231] = byItem231; - abyItem[232] = byItem232; abyItem[233] = byItem233; abyItem[234] = byItem234; abyItem[235] = byItem235; - abyItem[236] = byItem236; abyItem[237] = byItem237; abyItem[238] = byItem238; abyItem[239] = byItem239; - abyItem[240] = byItem240; abyItem[241] = byItem241; abyItem[242] = byItem242; abyItem[243] = byItem243; - abyItem[244] = byItem244; abyItem[245] = byItem245; abyItem[246] = byItem246; abyItem[247] = byItem247; - abyItem[248] = byItem248; abyItem[249] = byItem249; abyItem[250] = byItem250; abyItem[251] = byItem251; - abyItem[252] = byItem252; abyItem[253] = byItem253; abyItem[254] = byItem254; abyItem[255] = byItem255; - - // Zero anything after the NUL... - bool blNul = false; - for (int ii = 0; ii < abyItem.Length; ii++) - { - if (!blNul && (abyItem[ii] == 0)) - { - blNul = true; - } - else if (blNul) - { - abyItem[ii] = 0; - } - } - - // change encoding of byte array, then convert the bytes array to a string - string sz = Encoding.Unicode.GetString(Encoding.Convert(encoding ?? Language.GetEncoding(), Encoding.Unicode, abyItem)); - - // If the first character is a NUL, then return the empty string... - if (sz[0] == '\0') - { - return (""); - } - - // If we're running on a Mac, take off the prefix 'byte'... - if (a_blMayHavePrefix && TWPlatform.IsMacOSX) - { - sz = sz.Remove(0, 1); - } - - // If we detect a NUL, then split around it... - if (sz.IndexOf('\0') >= 0) - { - sz = sz.Split(new char[] { '\0' })[0]; - } - - // All done... - return (sz); - } - - /// - /// The normal set... - /// - /// - /// - /// - public void Set(string a_sz, Encoding? encoding = null) - { - SetValue(a_sz, true, encoding); - } - - /// - /// Use this on Mac OS X if you have a call that uses a string - /// that doesn't include the prefix byte... - /// - /// - /// - /// - public void SetNoPrefix(string a_sz, Encoding? encoding = null) - { - SetValue(a_sz, false, encoding); - } - - /// - /// Set our value... - /// - /// - /// - /// - private void SetValue(string a_sz, bool a_blMayHavePrefix, Encoding? encoding = null) - { - // If we're running on a Mac, tack on the prefix 'byte'... - if (a_sz == null) - { - a_sz = ""; - } - else if (a_blMayHavePrefix && TWPlatform.IsMacOSX) - { - a_sz = (char)a_sz.Length + a_sz; - } - - // Make sure that we're NUL padded... - string sz = - a_sz + - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; - if (sz.Length > 256) - { - sz = sz.Remove(256); - } - - // convert string to byte array, then change the encoding of the byte array - byte[] abyItem = Encoding.Convert(Encoding.Unicode, encoding ?? Language.GetEncoding(), Encoding.Unicode.GetBytes(sz)); - - // concert byte array to bytes - byItem000 = abyItem[0]; byItem001 = abyItem[1]; byItem002 = abyItem[2]; byItem003 = abyItem[3]; - byItem004 = abyItem[4]; byItem005 = abyItem[5]; byItem006 = abyItem[6]; byItem007 = abyItem[7]; - byItem008 = abyItem[8]; byItem009 = abyItem[9]; byItem010 = abyItem[10]; byItem011 = abyItem[11]; - byItem012 = abyItem[12]; byItem013 = abyItem[13]; byItem014 = abyItem[14]; byItem015 = abyItem[15]; - byItem016 = abyItem[16]; byItem017 = abyItem[17]; byItem018 = abyItem[18]; byItem019 = abyItem[19]; - byItem020 = abyItem[20]; byItem021 = abyItem[21]; byItem022 = abyItem[22]; byItem023 = abyItem[23]; - byItem024 = abyItem[24]; byItem025 = abyItem[25]; byItem026 = abyItem[26]; byItem027 = abyItem[27]; - byItem028 = abyItem[28]; byItem029 = abyItem[29]; byItem030 = abyItem[30]; byItem031 = abyItem[31]; - byItem032 = abyItem[32]; byItem033 = abyItem[33]; byItem034 = abyItem[34]; byItem035 = abyItem[35]; - byItem036 = abyItem[36]; byItem037 = abyItem[37]; byItem038 = abyItem[38]; byItem039 = abyItem[39]; - byItem040 = abyItem[40]; byItem041 = abyItem[41]; byItem042 = abyItem[42]; byItem043 = abyItem[43]; - byItem044 = abyItem[44]; byItem045 = abyItem[45]; byItem046 = abyItem[46]; byItem047 = abyItem[47]; - byItem048 = abyItem[48]; byItem049 = abyItem[49]; byItem050 = abyItem[50]; byItem051 = abyItem[51]; - byItem052 = abyItem[52]; byItem053 = abyItem[53]; byItem054 = abyItem[54]; byItem055 = abyItem[55]; - byItem056 = abyItem[56]; byItem057 = abyItem[57]; byItem058 = abyItem[58]; byItem059 = abyItem[59]; - byItem060 = abyItem[60]; byItem061 = abyItem[61]; byItem062 = abyItem[62]; byItem063 = abyItem[63]; - byItem064 = abyItem[64]; byItem065 = abyItem[65]; byItem066 = abyItem[66]; byItem067 = abyItem[67]; - byItem068 = abyItem[68]; byItem069 = abyItem[69]; byItem070 = abyItem[70]; byItem071 = abyItem[71]; - byItem072 = abyItem[72]; byItem073 = abyItem[73]; byItem074 = abyItem[74]; byItem075 = abyItem[75]; - byItem076 = abyItem[76]; byItem077 = abyItem[77]; byItem078 = abyItem[78]; byItem079 = abyItem[79]; - byItem080 = abyItem[80]; byItem081 = abyItem[81]; byItem082 = abyItem[82]; byItem083 = abyItem[83]; - byItem084 = abyItem[84]; byItem085 = abyItem[85]; byItem086 = abyItem[86]; byItem087 = abyItem[87]; - byItem088 = abyItem[88]; byItem089 = abyItem[89]; byItem090 = abyItem[90]; byItem091 = abyItem[91]; - byItem092 = abyItem[92]; byItem093 = abyItem[93]; byItem094 = abyItem[94]; byItem095 = abyItem[95]; - byItem096 = abyItem[96]; byItem097 = abyItem[97]; byItem098 = abyItem[98]; byItem099 = abyItem[99]; - byItem100 = abyItem[100]; byItem101 = abyItem[101]; byItem102 = abyItem[102]; byItem103 = abyItem[103]; - byItem104 = abyItem[104]; byItem105 = abyItem[105]; byItem106 = abyItem[106]; byItem107 = abyItem[107]; - byItem108 = abyItem[108]; byItem109 = abyItem[109]; byItem110 = abyItem[110]; byItem111 = abyItem[111]; - byItem112 = abyItem[112]; byItem113 = abyItem[113]; byItem114 = abyItem[114]; byItem115 = abyItem[115]; - byItem116 = abyItem[116]; byItem117 = abyItem[117]; byItem118 = abyItem[118]; byItem119 = abyItem[119]; - byItem120 = abyItem[120]; byItem121 = abyItem[121]; byItem122 = abyItem[122]; byItem123 = abyItem[123]; - byItem124 = abyItem[124]; byItem125 = abyItem[125]; byItem126 = abyItem[126]; byItem127 = abyItem[127]; - byItem128 = abyItem[128]; byItem129 = abyItem[129]; byItem130 = abyItem[130]; byItem131 = abyItem[131]; - byItem132 = abyItem[132]; byItem133 = abyItem[133]; byItem134 = abyItem[134]; byItem135 = abyItem[135]; - byItem136 = abyItem[136]; byItem137 = abyItem[137]; byItem138 = abyItem[138]; byItem139 = abyItem[139]; - byItem140 = abyItem[140]; byItem141 = abyItem[141]; byItem142 = abyItem[142]; byItem143 = abyItem[143]; - byItem144 = abyItem[144]; byItem145 = abyItem[145]; byItem146 = abyItem[146]; byItem147 = abyItem[147]; - byItem148 = abyItem[148]; byItem149 = abyItem[149]; byItem150 = abyItem[150]; byItem151 = abyItem[151]; - byItem152 = abyItem[152]; byItem153 = abyItem[153]; byItem154 = abyItem[154]; byItem155 = abyItem[155]; - byItem156 = abyItem[156]; byItem157 = abyItem[157]; byItem158 = abyItem[158]; byItem159 = abyItem[159]; - byItem160 = abyItem[160]; byItem161 = abyItem[161]; byItem162 = abyItem[162]; byItem163 = abyItem[163]; - byItem164 = abyItem[164]; byItem165 = abyItem[165]; byItem166 = abyItem[166]; byItem167 = abyItem[167]; - byItem168 = abyItem[168]; byItem169 = abyItem[169]; byItem170 = abyItem[170]; byItem171 = abyItem[171]; - byItem172 = abyItem[172]; byItem173 = abyItem[173]; byItem174 = abyItem[174]; byItem175 = abyItem[175]; - byItem176 = abyItem[176]; byItem177 = abyItem[177]; byItem178 = abyItem[178]; byItem179 = abyItem[179]; - byItem180 = abyItem[180]; byItem181 = abyItem[181]; byItem182 = abyItem[182]; byItem183 = abyItem[183]; - byItem184 = abyItem[184]; byItem185 = abyItem[185]; byItem186 = abyItem[186]; byItem187 = abyItem[187]; - byItem188 = abyItem[188]; byItem189 = abyItem[189]; byItem190 = abyItem[190]; byItem191 = abyItem[191]; - byItem192 = abyItem[192]; byItem193 = abyItem[193]; byItem194 = abyItem[194]; byItem195 = abyItem[195]; - byItem196 = abyItem[196]; byItem197 = abyItem[197]; byItem198 = abyItem[198]; byItem199 = abyItem[199]; - byItem200 = abyItem[200]; byItem201 = abyItem[201]; byItem202 = abyItem[202]; byItem203 = abyItem[203]; - byItem204 = abyItem[204]; byItem205 = abyItem[205]; byItem206 = abyItem[206]; byItem207 = abyItem[207]; - byItem208 = abyItem[208]; byItem209 = abyItem[209]; byItem210 = abyItem[210]; byItem211 = abyItem[211]; - byItem212 = abyItem[212]; byItem213 = abyItem[213]; byItem214 = abyItem[214]; byItem215 = abyItem[215]; - byItem216 = abyItem[216]; byItem217 = abyItem[217]; byItem218 = abyItem[218]; byItem219 = abyItem[219]; - byItem220 = abyItem[220]; byItem221 = abyItem[221]; byItem222 = abyItem[222]; byItem223 = abyItem[223]; - byItem224 = abyItem[224]; byItem225 = abyItem[225]; byItem226 = abyItem[226]; byItem227 = abyItem[227]; - byItem228 = abyItem[228]; byItem229 = abyItem[229]; byItem230 = abyItem[230]; byItem231 = abyItem[231]; - byItem232 = abyItem[232]; byItem233 = abyItem[233]; byItem234 = abyItem[234]; byItem235 = abyItem[235]; - byItem236 = abyItem[236]; byItem237 = abyItem[237]; byItem238 = abyItem[238]; byItem239 = abyItem[239]; - byItem240 = abyItem[240]; byItem241 = abyItem[241]; byItem242 = abyItem[242]; byItem243 = abyItem[243]; - byItem244 = abyItem[244]; byItem245 = abyItem[245]; byItem246 = abyItem[246]; byItem247 = abyItem[247]; - byItem248 = abyItem[248]; byItem249 = abyItem[249]; byItem250 = abyItem[250]; byItem251 = abyItem[251]; - byItem252 = abyItem[252]; byItem253 = abyItem[253]; byItem254 = abyItem[254]; byItem255 = abyItem[255]; - } - } - - #endregion - - - /////////////////////////////////////////////////////////////////////////////// - // Structure Definitions... - /////////////////////////////////////////////////////////////////////////////// - #region Structure Definitions.. - - /// - /// Fixed point structure type. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public partial struct TW_FIX32 - { - public short Whole; - public ushort Frac; - } - - /// - /// Defines a frame rectangle in ICAP_UNITS coordinates. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public partial struct TW_FRAME - { - public TW_FIX32 Left; - public TW_FIX32 Top; - public TW_FIX32 Right; - public TW_FIX32 Bottom; - } - - /// - /// Defines the parameters used for channel-specific transformation. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_DECODEFUNCTION - { - public TW_FIX32 StartIn; - public TW_FIX32 BreakIn; - public TW_FIX32 EndIn; - public TW_FIX32 StartOut; - public TW_FIX32 BreakOut; - public TW_FIX32 EndOut; - public TW_FIX32 Gamma; - public TW_FIX32 SampleCount; - } - - /// - /// Stores a Fixed point number in two parts, a whole and a fractional part. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_TRANSFORMSTAGE - { - public TW_DECODEFUNCTION Decode_0; - public TW_DECODEFUNCTION Decode_1; - public TW_DECODEFUNCTION Decode_2; - public TW_FIX32 Mix_0_0; - public TW_FIX32 Mix_0_1; - public TW_FIX32 Mix_0_2; - public TW_FIX32 Mix_1_0; - public TW_FIX32 Mix_1_1; - public TW_FIX32 Mix_1_2; - public TW_FIX32 Mix_2_0; - public TW_FIX32 Mix_2_1; - public TW_FIX32 Mix_2_2; - } - - /// - /// Stores a list of values for a capability, the ItemList is commented - /// out so that the caller can collect information about it with a - /// marshalling call... - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_ARRAY - { - public TWTY ItemType; - public uint NumItems; - //public byte[] ItemList; - } - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_ARRAY_MACOSX - { - public uint ItemType; - public uint NumItems; - //public byte[] ItemList; - } - - /// - /// Information about audio data. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_AUDIOINFO - { - public TW_STR255 Name; - public uint Reserved; - } - - /// - /// Used to register callbacks. - /// - [SuppressMessage("Microsoft.Design", "CA1049:TypesThatOwnNativeResourcesShouldBeDisposable")] - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_CALLBACK - { - [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] - public IntPtr CallBackProc; - public uint RefCon; - public ushort Message; - } - - /// - /// Used to register callbacks. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_CALLBACK2 - { - [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] - public IntPtr CallBackProc; - [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] - public UIntPtr RefCon; - public ushort Message; - } - - /// - /// Used by application to get/set capability from/in a data source. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2, CharSet = CharSet.Ansi)] - public partial struct TW_CAPABILITY - { - public CAP Cap; - public TWON ConType; - [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] - public IntPtr hContainer; - } - - /// - /// Defines a CIE XYZ space tri-stimulus value. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_CIEPOINT - { - public TW_FIX32 X; - public TW_FIX32 Y; - public TW_FIX32 Z; - } - - /// - /// Defines the mapping from an RGB color space device into CIE 1931 (XYZ) color space. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_CIECOLOR - { - public ushort ColorSpace; - public short LowEndian; - public short DeviceDependent; - public int VersionNumber; - public TW_TRANSFORMSTAGE StageABC; - public TW_TRANSFORMSTAGE StageLNM; - public TW_CIEPOINT WhitePoint; - public TW_CIEPOINT BlackPoint; - public TW_CIEPOINT WhitePaper; - public TW_CIEPOINT BlackInk; - public TW_FIX32 Samples; - } - - /// - /// Allows for a data source and application to pass custom data to each other. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_CUSTOMDSDATA - { - public uint InfoLength; - [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] - public IntPtr hData; - } - - /// - /// Provides information about the Event that was raised by the Source. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public partial struct TW_DEVICEEVENT - { - private uint _Event; - public TW_STR255 DeviceName; - public uint BatteryMinutes; - public short BatteryPercentage; - public int PowerSupply; - public TW_FIX32 XResolution; - public TW_FIX32 YResolution; - private uint _FlashUsed2; - public uint AutomaticCapture; - public uint TimeBeforeFirstCapture; - public uint TimeBetweenCaptures; - } - - /// - /// This structure holds the tri-stimulus color palette information for TW_PALETTE8 structures. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_ELEMENT8 - { - public byte Index; - public byte Channel1; - public byte Channel2; - public byte Channel3; - } - - /// - /// DAT_ENTRYPOINT. returns essential entry points. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_ENTRYPOINT - { - public UInt32 Size; - [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] - public IntPtr DSM_Entry; - [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] - public IntPtr DSM_MemAllocate; - [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] - public IntPtr DSM_MemFree; - [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] - public IntPtr DSM_MemLock; - [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] - public IntPtr DSM_MemUnlock; - } - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_ENTRYPOINT_LINUX64 - { - public long Size; - [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] - public IntPtr DSM_Entry; - [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] - public IntPtr DSM_MemAllocate; - [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] - public IntPtr DSM_MemFree; - [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] - public IntPtr DSM_MemLock; - [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] - public IntPtr DSM_MemUnlock; - } - public struct TW_ENTRYPOINT_DELEGATES - { - public UInt32 Size; - [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] - public IntPtr DSM_Entry; - public DSM_MEMALLOC DSM_MemAllocate; - public DSM_MEMFREE DSM_MemFree; - public DSM_MEMLOCK DSM_MemLock; - public DSM_MEMUNLOCK DSM_MemUnlock; - } - public delegate IntPtr DSM_MEMALLOC(uint size); - public delegate void DSM_MEMFREE(IntPtr handle); - public delegate IntPtr DSM_MEMLOCK(IntPtr handle); - public delegate void DSM_MEMUNLOCK(IntPtr handle); - - /// - /// Stores a group of enumerated values for a capability, the ItemList is - /// commented out so that the caller can collect information about it with - /// a marshalling call... - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_ENUMERATION - { - public TWTY ItemType; - public uint NumItems; - public uint CurrentIndex; - public uint DefaultIndex; - //public byte[] ItemList; - } - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_ENUMERATION_LINUX64 - { - public TWTY ItemType; - public ulong NumItems; - public ulong CurrentIndex; - public ulong DefaultIndex; - //public byte[] ItemList; - } - [StructLayout(LayoutKind.Sequential, Pack = 4)] - public struct TW_ENUMERATION_MACOSX - { - public uint ItemType; - public uint NumItems; - public uint CurrentIndex; - public uint DefaultIndex; - //public byte[] ItemList; - } - - /// - /// Used to pass application events/messages from the application to the Source. - /// - [SuppressMessage("Microsoft.Design", "CA1049:TypesThatOwnNativeResourcesShouldBeDisposable")] - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_EVENT - { - [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] - public IntPtr pEvent; - public ushort TWMessage; - } - - /// - /// DAT_FILTER... - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_FILTER_DESCRIPTOR - { - public UInt32 Size; - public UInt32 HueStart; - public UInt32 HueEnd; - public UInt32 SaturationStart; - public UInt32 SaturationEnd; - public UInt32 ValueStart; - public UInt32 ValueEnd; - public UInt32 Replacement; - } - - /// - /// DAT_FILTER... - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_FILTER - { - public UInt32 Size; - public UInt32 DescriptorCount; - public UInt32 MaxDescriptorCount; - public UInt32 Condition; - [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] - public IntPtr hDescriptors; - } - - /// - /// This structure is used to pass specific information between the data source and the application. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public partial struct TW_INFO - { - public TWEI InfoId; - public TWTY ItemType; - public ushort NumItems; - public TWRC ReturnCode; - [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] - public UIntPtr Item; - } - - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public partial struct TW_EXTIMAGEINFO - { - private uint NumInfos; - private TW_INFO Info_000; - private TW_INFO Info_001; - private TW_INFO Info_002; - private TW_INFO Info_003; - private TW_INFO Info_004; - private TW_INFO Info_005; - private TW_INFO Info_006; - private TW_INFO Info_007; - private TW_INFO Info_008; - private TW_INFO Info_009; - private TW_INFO Info_010; - private TW_INFO Info_011; - private TW_INFO Info_012; - private TW_INFO Info_013; - private TW_INFO Info_014; - private TW_INFO Info_015; - private TW_INFO Info_016; - private TW_INFO Info_017; - private TW_INFO Info_018; - private TW_INFO Info_019; - private TW_INFO Info_020; - private TW_INFO Info_021; - private TW_INFO Info_022; - private TW_INFO Info_023; - private TW_INFO Info_024; - private TW_INFO Info_025; - private TW_INFO Info_026; - private TW_INFO Info_027; - private TW_INFO Info_028; - private TW_INFO Info_029; - private TW_INFO Info_030; - private TW_INFO Info_031; - private TW_INFO Info_032; - private TW_INFO Info_033; - private TW_INFO Info_034; - private TW_INFO Info_035; - private TW_INFO Info_036; - private TW_INFO Info_037; - private TW_INFO Info_038; - private TW_INFO Info_039; - private TW_INFO Info_040; - private TW_INFO Info_041; - private TW_INFO Info_042; - private TW_INFO Info_043; - private TW_INFO Info_044; - private TW_INFO Info_045; - private TW_INFO Info_046; - private TW_INFO Info_047; - private TW_INFO Info_048; - private TW_INFO Info_049; - private TW_INFO Info_050; - private TW_INFO Info_051; - private TW_INFO Info_052; - private TW_INFO Info_053; - private TW_INFO Info_054; - private TW_INFO Info_055; - private TW_INFO Info_056; - private TW_INFO Info_057; - private TW_INFO Info_058; - private TW_INFO Info_059; - private TW_INFO Info_060; - private TW_INFO Info_061; - private TW_INFO Info_062; - private TW_INFO Info_063; - private TW_INFO Info_064; - private TW_INFO Info_065; - private TW_INFO Info_066; - private TW_INFO Info_067; - private TW_INFO Info_068; - private TW_INFO Info_069; - private TW_INFO Info_070; - private TW_INFO Info_071; - private TW_INFO Info_072; - private TW_INFO Info_073; - private TW_INFO Info_074; - private TW_INFO Info_075; - private TW_INFO Info_076; - private TW_INFO Info_077; - private TW_INFO Info_078; - private TW_INFO Info_079; - private TW_INFO Info_080; - private TW_INFO Info_081; - private TW_INFO Info_082; - private TW_INFO Info_083; - private TW_INFO Info_084; - private TW_INFO Info_085; - private TW_INFO Info_086; - private TW_INFO Info_087; - private TW_INFO Info_088; - private TW_INFO Info_089; - private TW_INFO Info_090; - private TW_INFO Info_091; - private TW_INFO Info_092; - private TW_INFO Info_093; - private TW_INFO Info_094; - private TW_INFO Info_095; - private TW_INFO Info_096; - private TW_INFO Info_097; - private TW_INFO Info_098; - private TW_INFO Info_099; - - // 200 seems overkill for anyone to request - // at once so I cut it down in half - - //private TW_INFO Info_100; - //private TW_INFO Info_101; - //private TW_INFO Info_102; - //private TW_INFO Info_103; - //private TW_INFO Info_104; - //private TW_INFO Info_105; - //private TW_INFO Info_106; - //private TW_INFO Info_107; - //private TW_INFO Info_108; - //private TW_INFO Info_109; - //private TW_INFO Info_110; - //private TW_INFO Info_111; - //private TW_INFO Info_112; - //private TW_INFO Info_113; - //private TW_INFO Info_114; - //private TW_INFO Info_115; - //private TW_INFO Info_116; - //private TW_INFO Info_117; - //private TW_INFO Info_118; - //private TW_INFO Info_119; - //private TW_INFO Info_120; - //private TW_INFO Info_121; - //private TW_INFO Info_122; - //private TW_INFO Info_123; - //private TW_INFO Info_124; - //private TW_INFO Info_125; - //private TW_INFO Info_126; - //private TW_INFO Info_127; - //private TW_INFO Info_128; - //private TW_INFO Info_129; - //private TW_INFO Info_130; - //private TW_INFO Info_131; - //private TW_INFO Info_132; - //private TW_INFO Info_133; - //private TW_INFO Info_134; - //private TW_INFO Info_135; - //private TW_INFO Info_136; - //private TW_INFO Info_137; - //private TW_INFO Info_138; - //private TW_INFO Info_139; - //private TW_INFO Info_140; - //private TW_INFO Info_141; - //private TW_INFO Info_142; - //private TW_INFO Info_143; - //private TW_INFO Info_144; - //private TW_INFO Info_145; - //private TW_INFO Info_146; - //private TW_INFO Info_147; - //private TW_INFO Info_148; - //private TW_INFO Info_149; - //private TW_INFO Info_150; - //private TW_INFO Info_151; - //private TW_INFO Info_152; - //private TW_INFO Info_153; - //private TW_INFO Info_154; - //private TW_INFO Info_155; - //private TW_INFO Info_156; - //private TW_INFO Info_157; - //private TW_INFO Info_158; - //private TW_INFO Info_159; - //private TW_INFO Info_160; - //private TW_INFO Info_161; - //private TW_INFO Info_162; - //private TW_INFO Info_163; - //private TW_INFO Info_164; - //private TW_INFO Info_165; - //private TW_INFO Info_166; - //private TW_INFO Info_167; - //private TW_INFO Info_168; - //private TW_INFO Info_169; - //private TW_INFO Info_170; - //private TW_INFO Info_171; - //private TW_INFO Info_172; - //private TW_INFO Info_173; - //private TW_INFO Info_174; - //private TW_INFO Info_175; - //private TW_INFO Info_176; - //private TW_INFO Info_177; - //private TW_INFO Info_178; - //private TW_INFO Info_179; - //private TW_INFO Info_180; - //private TW_INFO Info_181; - //private TW_INFO Info_182; - //private TW_INFO Info_183; - //private TW_INFO Info_184; - //private TW_INFO Info_185; - //private TW_INFO Info_186; - //private TW_INFO Info_187; - //private TW_INFO Info_188; - //private TW_INFO Info_189; - //private TW_INFO Info_190; - //private TW_INFO Info_191; - //private TW_INFO Info_192; - //private TW_INFO Info_193; - //private TW_INFO Info_194; - //private TW_INFO Info_195; - //private TW_INFO Info_196; - //private TW_INFO Info_197; - //private TW_INFO Info_198; - //private TW_INFO Info_199; - - public void Get(int a_uIndex, ref TW_INFO a_twinfo) - { - switch (a_uIndex) - { - default: return; - case 0: a_twinfo = Info_000; return; - case 1: a_twinfo = Info_001; return; - case 2: a_twinfo = Info_002; return; - case 3: a_twinfo = Info_003; return; - case 4: a_twinfo = Info_004; return; - case 5: a_twinfo = Info_005; return; - case 6: a_twinfo = Info_006; return; - case 7: a_twinfo = Info_007; return; - case 8: a_twinfo = Info_008; return; - case 9: a_twinfo = Info_009; return; - case 10: a_twinfo = Info_010; return; - case 11: a_twinfo = Info_011; return; - case 12: a_twinfo = Info_012; return; - case 13: a_twinfo = Info_013; return; - case 14: a_twinfo = Info_014; return; - case 15: a_twinfo = Info_015; return; - case 16: a_twinfo = Info_016; return; - case 17: a_twinfo = Info_017; return; - case 18: a_twinfo = Info_018; return; - case 19: a_twinfo = Info_019; return; - case 20: a_twinfo = Info_020; return; - case 21: a_twinfo = Info_021; return; - case 22: a_twinfo = Info_022; return; - case 23: a_twinfo = Info_023; return; - case 24: a_twinfo = Info_024; return; - case 25: a_twinfo = Info_025; return; - case 26: a_twinfo = Info_026; return; - case 27: a_twinfo = Info_027; return; - case 28: a_twinfo = Info_028; return; - case 29: a_twinfo = Info_029; return; - case 30: a_twinfo = Info_030; return; - case 31: a_twinfo = Info_031; return; - case 32: a_twinfo = Info_032; return; - case 33: a_twinfo = Info_033; return; - case 34: a_twinfo = Info_034; return; - case 35: a_twinfo = Info_035; return; - case 36: a_twinfo = Info_036; return; - case 37: a_twinfo = Info_037; return; - case 38: a_twinfo = Info_038; return; - case 39: a_twinfo = Info_039; return; - case 40: a_twinfo = Info_040; return; - case 41: a_twinfo = Info_041; return; - case 42: a_twinfo = Info_042; return; - case 43: a_twinfo = Info_043; return; - case 44: a_twinfo = Info_044; return; - case 45: a_twinfo = Info_045; return; - case 46: a_twinfo = Info_046; return; - case 47: a_twinfo = Info_047; return; - case 48: a_twinfo = Info_048; return; - case 49: a_twinfo = Info_049; return; - case 50: a_twinfo = Info_050; return; - case 51: a_twinfo = Info_051; return; - case 52: a_twinfo = Info_052; return; - case 53: a_twinfo = Info_053; return; - case 54: a_twinfo = Info_054; return; - case 55: a_twinfo = Info_055; return; - case 56: a_twinfo = Info_056; return; - case 57: a_twinfo = Info_057; return; - case 58: a_twinfo = Info_058; return; - case 59: a_twinfo = Info_059; return; - case 60: a_twinfo = Info_060; return; - case 61: a_twinfo = Info_061; return; - case 62: a_twinfo = Info_062; return; - case 63: a_twinfo = Info_063; return; - case 64: a_twinfo = Info_064; return; - case 65: a_twinfo = Info_065; return; - case 66: a_twinfo = Info_066; return; - case 67: a_twinfo = Info_067; return; - case 68: a_twinfo = Info_068; return; - case 69: a_twinfo = Info_069; return; - case 70: a_twinfo = Info_070; return; - case 71: a_twinfo = Info_071; return; - case 72: a_twinfo = Info_072; return; - case 73: a_twinfo = Info_073; return; - case 74: a_twinfo = Info_074; return; - case 75: a_twinfo = Info_075; return; - case 76: a_twinfo = Info_076; return; - case 77: a_twinfo = Info_077; return; - case 78: a_twinfo = Info_078; return; - case 79: a_twinfo = Info_079; return; - case 80: a_twinfo = Info_080; return; - case 81: a_twinfo = Info_081; return; - case 82: a_twinfo = Info_082; return; - case 83: a_twinfo = Info_083; return; - case 84: a_twinfo = Info_084; return; - case 85: a_twinfo = Info_085; return; - case 86: a_twinfo = Info_086; return; - case 87: a_twinfo = Info_087; return; - case 88: a_twinfo = Info_088; return; - case 89: a_twinfo = Info_089; return; - case 90: a_twinfo = Info_090; return; - case 91: a_twinfo = Info_091; return; - case 92: a_twinfo = Info_092; return; - case 93: a_twinfo = Info_093; return; - case 94: a_twinfo = Info_094; return; - case 95: a_twinfo = Info_095; return; - case 96: a_twinfo = Info_096; return; - case 97: a_twinfo = Info_097; return; - case 98: a_twinfo = Info_098; return; - case 99: a_twinfo = Info_099; return; - //case 100: a_twinfo = Info_100; return; - //case 101: a_twinfo = Info_101; return; - //case 102: a_twinfo = Info_102; return; - //case 103: a_twinfo = Info_103; return; - //case 104: a_twinfo = Info_104; return; - //case 105: a_twinfo = Info_105; return; - //case 106: a_twinfo = Info_106; return; - //case 107: a_twinfo = Info_107; return; - //case 108: a_twinfo = Info_108; return; - //case 109: a_twinfo = Info_109; return; - //case 110: a_twinfo = Info_110; return; - //case 111: a_twinfo = Info_111; return; - //case 112: a_twinfo = Info_112; return; - //case 113: a_twinfo = Info_113; return; - //case 114: a_twinfo = Info_114; return; - //case 115: a_twinfo = Info_115; return; - //case 116: a_twinfo = Info_116; return; - //case 117: a_twinfo = Info_117; return; - //case 118: a_twinfo = Info_118; return; - //case 119: a_twinfo = Info_119; return; - //case 120: a_twinfo = Info_120; return; - //case 121: a_twinfo = Info_121; return; - //case 122: a_twinfo = Info_122; return; - //case 123: a_twinfo = Info_123; return; - //case 124: a_twinfo = Info_124; return; - //case 125: a_twinfo = Info_125; return; - //case 126: a_twinfo = Info_126; return; - //case 127: a_twinfo = Info_127; return; - //case 128: a_twinfo = Info_128; return; - //case 129: a_twinfo = Info_129; return; - //case 130: a_twinfo = Info_130; return; - //case 131: a_twinfo = Info_131; return; - //case 132: a_twinfo = Info_132; return; - //case 133: a_twinfo = Info_133; return; - //case 134: a_twinfo = Info_134; return; - //case 135: a_twinfo = Info_135; return; - //case 136: a_twinfo = Info_136; return; - //case 137: a_twinfo = Info_137; return; - //case 138: a_twinfo = Info_138; return; - //case 139: a_twinfo = Info_139; return; - //case 140: a_twinfo = Info_140; return; - //case 141: a_twinfo = Info_141; return; - //case 142: a_twinfo = Info_142; return; - //case 143: a_twinfo = Info_143; return; - //case 144: a_twinfo = Info_144; return; - //case 145: a_twinfo = Info_145; return; - //case 146: a_twinfo = Info_146; return; - //case 147: a_twinfo = Info_147; return; - //case 148: a_twinfo = Info_148; return; - //case 149: a_twinfo = Info_149; return; - //case 150: a_twinfo = Info_150; return; - //case 151: a_twinfo = Info_151; return; - //case 152: a_twinfo = Info_152; return; - //case 153: a_twinfo = Info_153; return; - //case 154: a_twinfo = Info_154; return; - //case 155: a_twinfo = Info_155; return; - //case 156: a_twinfo = Info_156; return; - //case 157: a_twinfo = Info_157; return; - //case 158: a_twinfo = Info_158; return; - //case 159: a_twinfo = Info_159; return; - //case 160: a_twinfo = Info_160; return; - //case 161: a_twinfo = Info_161; return; - //case 162: a_twinfo = Info_162; return; - //case 163: a_twinfo = Info_163; return; - //case 164: a_twinfo = Info_164; return; - //case 165: a_twinfo = Info_165; return; - //case 166: a_twinfo = Info_166; return; - //case 167: a_twinfo = Info_167; return; - //case 168: a_twinfo = Info_168; return; - //case 169: a_twinfo = Info_169; return; - //case 170: a_twinfo = Info_170; return; - //case 171: a_twinfo = Info_171; return; - //case 172: a_twinfo = Info_172; return; - //case 173: a_twinfo = Info_173; return; - //case 174: a_twinfo = Info_174; return; - //case 175: a_twinfo = Info_175; return; - //case 176: a_twinfo = Info_176; return; - //case 177: a_twinfo = Info_177; return; - //case 178: a_twinfo = Info_178; return; - //case 179: a_twinfo = Info_179; return; - //case 180: a_twinfo = Info_180; return; - //case 181: a_twinfo = Info_181; return; - //case 182: a_twinfo = Info_182; return; - //case 183: a_twinfo = Info_183; return; - //case 184: a_twinfo = Info_184; return; - //case 185: a_twinfo = Info_185; return; - //case 186: a_twinfo = Info_186; return; - //case 187: a_twinfo = Info_187; return; - //case 188: a_twinfo = Info_188; return; - //case 189: a_twinfo = Info_189; return; - //case 190: a_twinfo = Info_190; return; - //case 191: a_twinfo = Info_191; return; - //case 192: a_twinfo = Info_192; return; - //case 193: a_twinfo = Info_193; return; - //case 194: a_twinfo = Info_194; return; - //case 195: a_twinfo = Info_195; return; - //case 196: a_twinfo = Info_196; return; - //case 197: a_twinfo = Info_197; return; - //case 198: a_twinfo = Info_198; return; - //case 199: a_twinfo = Info_199; return; - } - } - - public void Set(int a_uIndex, ref TW_INFO a_twinfo) - { - switch (a_uIndex) - { - default: return; - case 0: Info_000 = a_twinfo; return; - case 1: Info_001 = a_twinfo; return; - case 2: Info_002 = a_twinfo; return; - case 3: Info_003 = a_twinfo; return; - case 4: Info_004 = a_twinfo; return; - case 5: Info_005 = a_twinfo; return; - case 6: Info_006 = a_twinfo; return; - case 7: Info_007 = a_twinfo; return; - case 8: Info_008 = a_twinfo; return; - case 9: Info_009 = a_twinfo; return; - case 10: Info_010 = a_twinfo; return; - case 11: Info_011 = a_twinfo; return; - case 12: Info_012 = a_twinfo; return; - case 13: Info_013 = a_twinfo; return; - case 14: Info_014 = a_twinfo; return; - case 15: Info_015 = a_twinfo; return; - case 16: Info_016 = a_twinfo; return; - case 17: Info_017 = a_twinfo; return; - case 18: Info_018 = a_twinfo; return; - case 19: Info_019 = a_twinfo; return; - case 20: Info_020 = a_twinfo; return; - case 21: Info_021 = a_twinfo; return; - case 22: Info_022 = a_twinfo; return; - case 23: Info_023 = a_twinfo; return; - case 24: Info_024 = a_twinfo; return; - case 25: Info_025 = a_twinfo; return; - case 26: Info_026 = a_twinfo; return; - case 27: Info_027 = a_twinfo; return; - case 28: Info_028 = a_twinfo; return; - case 29: Info_029 = a_twinfo; return; - case 30: Info_030 = a_twinfo; return; - case 31: Info_031 = a_twinfo; return; - case 32: Info_032 = a_twinfo; return; - case 33: Info_033 = a_twinfo; return; - case 34: Info_034 = a_twinfo; return; - case 35: Info_035 = a_twinfo; return; - case 36: Info_036 = a_twinfo; return; - case 37: Info_037 = a_twinfo; return; - case 38: Info_038 = a_twinfo; return; - case 39: Info_039 = a_twinfo; return; - case 40: Info_040 = a_twinfo; return; - case 41: Info_041 = a_twinfo; return; - case 42: Info_042 = a_twinfo; return; - case 43: Info_043 = a_twinfo; return; - case 44: Info_044 = a_twinfo; return; - case 45: Info_045 = a_twinfo; return; - case 46: Info_046 = a_twinfo; return; - case 47: Info_047 = a_twinfo; return; - case 48: Info_048 = a_twinfo; return; - case 49: Info_049 = a_twinfo; return; - case 50: Info_050 = a_twinfo; return; - case 51: Info_051 = a_twinfo; return; - case 52: Info_052 = a_twinfo; return; - case 53: Info_053 = a_twinfo; return; - case 54: Info_054 = a_twinfo; return; - case 55: Info_055 = a_twinfo; return; - case 56: Info_056 = a_twinfo; return; - case 57: Info_057 = a_twinfo; return; - case 58: Info_058 = a_twinfo; return; - case 59: Info_059 = a_twinfo; return; - case 60: Info_060 = a_twinfo; return; - case 61: Info_061 = a_twinfo; return; - case 62: Info_062 = a_twinfo; return; - case 63: Info_063 = a_twinfo; return; - case 64: Info_064 = a_twinfo; return; - case 65: Info_065 = a_twinfo; return; - case 66: Info_066 = a_twinfo; return; - case 67: Info_067 = a_twinfo; return; - case 68: Info_068 = a_twinfo; return; - case 69: Info_069 = a_twinfo; return; - case 70: Info_070 = a_twinfo; return; - case 71: Info_071 = a_twinfo; return; - case 72: Info_072 = a_twinfo; return; - case 73: Info_073 = a_twinfo; return; - case 74: Info_074 = a_twinfo; return; - case 75: Info_075 = a_twinfo; return; - case 76: Info_076 = a_twinfo; return; - case 77: Info_077 = a_twinfo; return; - case 78: Info_078 = a_twinfo; return; - case 79: Info_079 = a_twinfo; return; - case 80: Info_080 = a_twinfo; return; - case 81: Info_081 = a_twinfo; return; - case 82: Info_082 = a_twinfo; return; - case 83: Info_083 = a_twinfo; return; - case 84: Info_084 = a_twinfo; return; - case 85: Info_085 = a_twinfo; return; - case 86: Info_086 = a_twinfo; return; - case 87: Info_087 = a_twinfo; return; - case 88: Info_088 = a_twinfo; return; - case 89: Info_089 = a_twinfo; return; - case 90: Info_090 = a_twinfo; return; - case 91: Info_091 = a_twinfo; return; - case 92: Info_092 = a_twinfo; return; - case 93: Info_093 = a_twinfo; return; - case 94: Info_094 = a_twinfo; return; - case 95: Info_095 = a_twinfo; return; - case 96: Info_096 = a_twinfo; return; - case 97: Info_097 = a_twinfo; return; - case 98: Info_098 = a_twinfo; return; - case 99: Info_099 = a_twinfo; return; - //case 100: Info_100 = a_twinfo; return; - //case 101: Info_101 = a_twinfo; return; - //case 102: Info_102 = a_twinfo; return; - //case 103: Info_103 = a_twinfo; return; - //case 104: Info_104 = a_twinfo; return; - //case 105: Info_105 = a_twinfo; return; - //case 106: Info_106 = a_twinfo; return; - //case 107: Info_107 = a_twinfo; return; - //case 108: Info_108 = a_twinfo; return; - //case 109: Info_109 = a_twinfo; return; - //case 110: Info_110 = a_twinfo; return; - //case 111: Info_111 = a_twinfo; return; - //case 112: Info_112 = a_twinfo; return; - //case 113: Info_113 = a_twinfo; return; - //case 114: Info_114 = a_twinfo; return; - //case 115: Info_115 = a_twinfo; return; - //case 116: Info_116 = a_twinfo; return; - //case 117: Info_117 = a_twinfo; return; - //case 118: Info_118 = a_twinfo; return; - //case 119: Info_119 = a_twinfo; return; - //case 120: Info_120 = a_twinfo; return; - //case 121: Info_121 = a_twinfo; return; - //case 122: Info_122 = a_twinfo; return; - //case 123: Info_123 = a_twinfo; return; - //case 124: Info_124 = a_twinfo; return; - //case 125: Info_125 = a_twinfo; return; - //case 126: Info_126 = a_twinfo; return; - //case 127: Info_127 = a_twinfo; return; - //case 128: Info_128 = a_twinfo; return; - //case 129: Info_129 = a_twinfo; return; - //case 130: Info_130 = a_twinfo; return; - //case 131: Info_131 = a_twinfo; return; - //case 132: Info_132 = a_twinfo; return; - //case 133: Info_133 = a_twinfo; return; - //case 134: Info_134 = a_twinfo; return; - //case 135: Info_135 = a_twinfo; return; - //case 136: Info_136 = a_twinfo; return; - //case 137: Info_137 = a_twinfo; return; - //case 138: Info_138 = a_twinfo; return; - //case 139: Info_139 = a_twinfo; return; - //case 140: Info_140 = a_twinfo; return; - //case 141: Info_141 = a_twinfo; return; - //case 142: Info_142 = a_twinfo; return; - //case 143: Info_143 = a_twinfo; return; - //case 144: Info_144 = a_twinfo; return; - //case 145: Info_145 = a_twinfo; return; - //case 146: Info_146 = a_twinfo; return; - //case 147: Info_147 = a_twinfo; return; - //case 148: Info_148 = a_twinfo; return; - //case 149: Info_149 = a_twinfo; return; - //case 150: Info_150 = a_twinfo; return; - //case 151: Info_151 = a_twinfo; return; - //case 152: Info_152 = a_twinfo; return; - //case 153: Info_153 = a_twinfo; return; - //case 154: Info_154 = a_twinfo; return; - //case 155: Info_155 = a_twinfo; return; - //case 156: Info_156 = a_twinfo; return; - //case 157: Info_157 = a_twinfo; return; - //case 158: Info_158 = a_twinfo; return; - //case 159: Info_159 = a_twinfo; return; - //case 160: Info_160 = a_twinfo; return; - //case 161: Info_161 = a_twinfo; return; - //case 162: Info_162 = a_twinfo; return; - //case 163: Info_163 = a_twinfo; return; - //case 164: Info_164 = a_twinfo; return; - //case 165: Info_165 = a_twinfo; return; - //case 166: Info_166 = a_twinfo; return; - //case 167: Info_167 = a_twinfo; return; - //case 168: Info_168 = a_twinfo; return; - //case 169: Info_169 = a_twinfo; return; - //case 170: Info_170 = a_twinfo; return; - //case 171: Info_171 = a_twinfo; return; - //case 172: Info_172 = a_twinfo; return; - //case 173: Info_173 = a_twinfo; return; - //case 174: Info_174 = a_twinfo; return; - //case 175: Info_175 = a_twinfo; return; - //case 176: Info_176 = a_twinfo; return; - //case 177: Info_177 = a_twinfo; return; - //case 178: Info_178 = a_twinfo; return; - //case 179: Info_179 = a_twinfo; return; - //case 180: Info_180 = a_twinfo; return; - //case 181: Info_181 = a_twinfo; return; - //case 182: Info_182 = a_twinfo; return; - //case 183: Info_183 = a_twinfo; return; - //case 184: Info_184 = a_twinfo; return; - //case 185: Info_185 = a_twinfo; return; - //case 186: Info_186 = a_twinfo; return; - //case 187: Info_187 = a_twinfo; return; - //case 188: Info_188 = a_twinfo; return; - //case 189: Info_189 = a_twinfo; return; - //case 190: Info_190 = a_twinfo; return; - //case 191: Info_191 = a_twinfo; return; - //case 192: Info_192 = a_twinfo; return; - //case 193: Info_193 = a_twinfo; return; - //case 194: Info_194 = a_twinfo; return; - //case 195: Info_195 = a_twinfo; return; - //case 196: Info_196 = a_twinfo; return; - //case 197: Info_197 = a_twinfo; return; - //case 198: Info_198 = a_twinfo; return; - //case 199: Info_199 = a_twinfo; return; - } - } - } - - /// - /// Provides information about the currently selected device. - /// TBD -- need a 32/64 bit solution for this mess - /// - [SuppressMessage("Microsoft.Portability", "CA1900:ValueTypeFieldsShouldBePortable", MessageId = "ModifiedTimeDate")] - [SuppressMessage("Microsoft.Portability", "CA1900:ValueTypeFieldsShouldBePortable", MessageId = "CreateTimeDate")] - [StructLayout(LayoutKind.Explicit, Pack = 2)] - public struct TW_FILESYSTEM - { - [FieldOffset(0)] - public TW_STR255 InputName; - - [FieldOffset(256)] - public TW_STR255 OutputName; - - [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] - [FieldOffset(512)] - public IntPtr Context; - - [FieldOffset(520)] - public Int32 Recursive; - [FieldOffset(520)] - public UInt16 Subdirectories; - - [FieldOffset(524)] - public Int32 FileType; - [FieldOffset(524)] - public UInt32 FileSystemType; - - [FieldOffset(528)] - public UInt32 Size; - - [FieldOffset(532)] - public TW_STR32 CreateTimeDate; - - [FieldOffset(566)] - public TW_STR32 ModifiedTimeDate; - - [FieldOffset(600)] - public UInt32 FreeSpace; - - [FieldOffset(604)] - public UInt32 NewImageSize; - - [FieldOffset(608)] - public UInt32 NumberOfFiles; - - [FieldOffset(612)] - public UInt32 NumberOfSnippets; - - [FieldOffset(616)] - public UInt32 DeviceGroupMask; - - [FieldOffset(620)] - public byte Reserved; - - [FieldOffset(1127)] // 620 + 508 - 1 - private byte ReservedEnd; - } - [SuppressMessage("Microsoft.Portability", "CA1900:ValueTypeFieldsShouldBePortable", MessageId = "ModifiedTimeDate")] - [StructLayout(LayoutKind.Explicit, Pack = 2)] - public struct TW_FILESYSTEM_LEGACY - { - [FieldOffset(0)] - public TW_STR255 InputName; - - [FieldOffset(256)] - public TW_STR255 OutputName; - - [FieldOffset(512)] - public UInt32 Context; - - [FieldOffset(516)] - public Int32 Recursive; - [FieldOffset(516)] - public UInt16 Subdirectories; - - [FieldOffset(520)] - public Int32 FileType; - [FieldOffset(520)] - public UInt32 FileSystemType; - - [FieldOffset(524)] - public UInt32 Size; - - [FieldOffset(528)] - public TW_STR32 CreateTimeDate; - - [FieldOffset(562)] - public TW_STR32 ModifiedTimeDate; - - [FieldOffset(596)] - public UInt32 FreeSpace; - - [FieldOffset(600)] - public UInt32 NewImageSize; - - [FieldOffset(604)] - public UInt32 NumberOfFiles; - - [FieldOffset(608)] - public UInt32 NumberOfSnippets; - - [FieldOffset(612)] - public UInt32 DeviceGroupMask; - - [FieldOffset(616)] - public byte Reserved; - - [FieldOffset(1123)] // 616 + 508 - 1 - private byte ReservedEnd; - } - - /// - /// This structure is used by the application to specify a set of mapping values to be applied to grayscale data. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_GRAYRESPONSE - { - public TW_ELEMENT8 Response_00; - } - - /// - /// A general way to describe the version of software that is running. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2, CharSet = CharSet.Ansi)] - public partial struct TW_VERSION - { - public ushort MajorNum; - public ushort MinorNum; - public TWLG Language; - public TWCY Country; - public TW_STR32 Info; - } - - /// - /// Provides identification information about a TWAIN entity. - /// The use of Padding is there to allow us to use the structure - /// with Linux 64-bit systems where the TW_INT32 and TW_UINT32 - /// types were long, and therefore 64-bits in size. This should - /// have no impact with well-behaved systems that have these types - /// as 32-bit, but should prevent memory corruption in all other - /// situations... - /// - [StructLayout(LayoutKind.Sequential, Pack = 2, CharSet = CharSet.Ansi)] - public partial struct TW_IDENTITY - { - public ulong Id; - public TW_VERSION Version; - public ushort ProtocolMajor; - public ushort ProtocolMinor; - public uint SupportedGroups; - public TW_STR32 Manufacturer; - public TW_STR32 ProductFamily; - public TW_STR32 ProductName; - } - [StructLayout(LayoutKind.Sequential, Pack = 2, CharSet = CharSet.Ansi)] - public partial struct TW_IDENTITY_LEGACY - { - public uint Id; - public TW_VERSION Version; - public ushort ProtocolMajor; - public ushort ProtocolMinor; - public uint SupportedGroups; - public TW_STR32 Manufacturer; - public TW_STR32 ProductFamily; - public TW_STR32 ProductName; - private UInt64 Padding; // accounts for Id and SupportedGroups - } - [StructLayout(LayoutKind.Sequential, Pack = 2, CharSet = CharSet.Ansi)] - public struct TW_IDENTITY_LINUX64 - { - public ulong Id; - public TW_VERSION Version; - public ushort ProtocolMajor; - public ushort ProtocolMinor; - public ulong SupportedGroups; - public TW_STR32 Manufacturer; - public TW_STR32 ProductFamily; - public TW_STR32 ProductName; - } - [StructLayout(LayoutKind.Sequential, Pack = 2, CharSet = CharSet.Ansi)] - public partial struct TW_IDENTITY_MACOSX - { - public uint Id; - public TW_VERSION Version; - public ushort ProtocolMajor; - public ushort ProtocolMinor; - private ushort padding; - public uint SupportedGroups; - public TW_STR32 Manufacturer; - public TW_STR32 ProductFamily; - public TW_STR32 ProductName; - } - - /// - /// Describes the “real” image data, that is, the complete image being transferred between the Source and application. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public partial struct TW_IMAGEINFO - { - public TW_FIX32 XResolution; - public TW_FIX32 YResolution; - public int ImageWidth; - public int ImageLength; - public short SamplesPerPixel; - public short BitsPerSample_0; - public short BitsPerSample_1; - public short BitsPerSample_2; - public short BitsPerSample_3; - public short BitsPerSample_4; - public short BitsPerSample_5; - public short BitsPerSample_6; - public short BitsPerSample_7; - public short BitsPerPixel; - public TW_BOOL Planar; - public TWPT PixelType; - public TWCP Compression; - } - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_IMAGEINFO_LINUX64 - { - public TW_FIX32 XResolution; - public TW_FIX32 YResolution; - public int ImageWidth; - public int ImageLength; - public short SamplesPerPixel; - public short BitsPerSample_0; - public short BitsPerSample_1; - public short BitsPerSample_2; - public short BitsPerSample_3; - public short BitsPerSample_4; - public short BitsPerSample_5; - public short BitsPerSample_6; - public short BitsPerSample_7; - public short BitsPerPixel; - public TW_BOOL Planar; - public TWPT PixelType; - public TWCP Compression; - } - - /// - /// Involves information about the original size of the acquired image. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_IMAGELAYOUT - { - public TW_FRAME Frame; - public uint DocumentNumber; - public uint PageNumber; - public uint FrameNumber; - } - - /// - /// Provides information for managing memory buffers. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_MEMORY - { - public uint Flags; - public uint Length; - [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] - public IntPtr TheMem; - } - - /// - /// Describes the form of the acquired data being passed from the Source to the application. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public partial struct TW_IMAGEMEMXFER - { - public ushort Compression; - public uint BytesPerRow; - public uint Columns; - public uint Rows; - public uint XOffset; - public uint YOffset; - public uint BytesWritten; - public TW_MEMORY Memory; - } - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public partial struct TW_IMAGEMEMXFER_LINUX64 - { - public ushort Compression; - public UInt64 BytesPerRow; - public UInt64 Columns; - public UInt64 Rows; - public UInt64 XOffset; - public UInt64 YOffset; - public UInt64 BytesWritten; - public UInt64 MemoryFlags; - public UInt64 MemoryLength; - [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] - public IntPtr MemoryTheMem; - } - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public partial struct TW_IMAGEMEMXFER_MACOSX - { - public uint Compression; - public uint BytesPerRow; - public uint Columns; - public uint Rows; - public uint XOffset; - public uint YOffset; - public uint BytesWritten; - public TW_MEMORY Memory; - } - - /// - /// Describes the information necessary to transfer a JPEG-compressed image. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_JPEGCOMPRESSION - { - public ushort ColorSpace; - public uint SubSampling; - public ushort NumComponents; - public ushort QuantMap_0; - public ushort QuantMap_1; - public ushort QuantMap_2; - public ushort QuantMap_3; - public TW_MEMORY QuantTable_0; - public TW_MEMORY QuantTable_1; - public TW_MEMORY QuantTable_2; - public TW_MEMORY QuantTable_3; - public ushort HuffmanMap_0; - public ushort HuffmanMap_1; - public ushort HuffmanMap_2; - public ushort HuffmanMap_3; - public TW_MEMORY HuffmanDC_0; - public TW_MEMORY HuffmanDC_1; - public TW_MEMORY HuffmanAC_0; - public TW_MEMORY HuffmanAC_2; - } - - /// - /// Collects scanning metrics after returning to state 4 - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_METRICS - { - public uint SizeOf; - public uint ImageCount; - public uint SheetCount; - } - - /// - /// Stores a single value (item) which describes a capability. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_ONEVALUE - { - public TWTY ItemType; - // public uint Item; - } - [StructLayout(LayoutKind.Sequential, Pack = 4)] - public struct TW_ONEVALUE_MACOSX - { - public uint ItemType; - // public uint Item; - } - - /// - /// This structure holds the color palette information. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_PALETTE8 - { - public ushort Flags; - public ushort Length; - public TW_ELEMENT8 Colors_000; - } - - /// - /// Used to bypass the TWAIN protocol when communicating with a device. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_PASSTHRU - { - [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] - public IntPtr pCommand; - public uint CommandBytes; - public int Direction; - [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] - public IntPtr pData; - public uint DataBytes; - public uint DataBytesXfered; - } - - /// - /// This structure tells the application how many more complete transfers the Source currently has available. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_PENDINGXFERS - { - public static TW_PENDINGXFERS DONTCARE() - { - return new TW_PENDINGXFERS { Count = -1 }; - } - - public short Count; - public uint EOJ; - } - - /// - /// Stores a range of individual values describing a capability. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_RANGE - { - public TWTY ItemType; - public uint MinValue; - public uint MaxValue; - public uint StepSize; - public uint DefaultValue; - public uint CurrentValue; - } - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_RANGE_LINUX64 - { - public TWTY ItemType; - public ulong MinValue; - public ulong MaxValue; - public ulong StepSize; - public ulong DefaultValue; - public ulong CurrentValue; - } - [StructLayout(LayoutKind.Sequential, Pack = 4)] - public struct TW_RANGE_MACOSX - { - public uint ItemType; - public uint MinValue; - public uint MaxValue; - public uint StepSize; - public uint DefaultValue; - public uint CurrentValue; - } - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_RANGE_FIX32 - { - public TWTY ItemType; - public TW_FIX32 MinValue; - public TW_FIX32 MaxValue; - public TW_FIX32 StepSize; - public TW_FIX32 DefaultValue; - public TW_FIX32 CurrentValue; - } - [StructLayout(LayoutKind.Sequential, Pack = 4)] - public struct TW_RANGE_FIX32_MACOSX - { - public uint ItemType; - public TW_FIX32 MinValue; - public TW_FIX32 MaxValue; - public TW_FIX32 StepSize; - public TW_FIX32 DefaultValue; - public TW_FIX32 CurrentValue; - } - - /// - /// This structure is used by the application to specify a set of mapping values to be applied to RGB color data. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_RGBRESPONSE - { - public TW_ELEMENT8 Response_00; - } - - /// - /// Describes the file format and file specification information for a transfer through a disk file. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public struct TW_SETUPFILEXFER - { - public TW_STR255 FileName; - public TWFF Format; - public short VRefNum; - } - - /// - /// Provides the application information about the Source’s requirements and preferences regarding allocation of transfer buffer(s). - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public partial struct TW_SETUPMEMXFER - { - public uint MinBufSize; - public uint MaxBufSize; - public uint Preferred; - } - - /// - /// Describes the status of a source. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public partial struct TW_STATUS - { - public TWCC ConditionCode; - public ushort Data; - } - - /// - /// Translates the contents of Status into a localized UTF8string. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2)] - public partial struct TW_STATUSUTF8 - { - public TW_STATUS Status; - public uint Size; - [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] - public IntPtr UTF8string; - } - - /// - /// Passthru for TWAIN Direct tasks. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2, CharSet = CharSet.Ansi)] - public struct TW_TWAINDIRECT - { - public uint SizeOf; - public ushort CommunicationManager; - [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] - public IntPtr Send; - public uint SendSize; - [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] - public IntPtr Receive; - public uint ReceiveSize; - } - - /// - /// This structure is used to handle the user interface coordination between an application and a Source. - /// - [StructLayout(LayoutKind.Sequential, Pack = 2, CharSet = CharSet.Ansi)] - public struct TW_USERINTERFACE - { - public ushort ShowUI; - public ushort ModalUI; - [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] - public IntPtr hParent; - } - - #endregion - - - /////////////////////////////////////////////////////////////////////////////// - // Generic Constants... - /////////////////////////////////////////////////////////////////////////////// - #region Generic Constants... - - /// - /// Container Types... - /// - public enum TWON : ushort - { - ARRAY = 3, - ENUMERATION = 4, - ONEVALUE = 5, - RANGE = 6, - - ICONID = 962, - DSMID = 461, - DSMCODEID = 63, - - DONTCARE = 0xffff - } - - ///// - ///// Don't care values... - ///// - //public const byte TWON_DONTCARE8 = 0xff; - //public const ushort TWON_DONTCARE16 = 0xff; - //public const uint TWON_DONTCARE32 = 0xffffffff; - - /// - /// Flags used in TW_MEMORY structure. - /// - [Flags] - public enum TWMF : ushort - { - APPOWNS = 0x0001, - DSMOWNS = 0x0002, - DSOWNS = 0x0004, - POINTER = 0x0008, - HANDLE = 0x0010 - } - - /// - /// Type values... - /// - public enum TWTY : ushort - { - Invalid = 0xffff, - - INT8 = 0x0000, - INT16 = 0x0001, - INT32 = 0x0002, - - UINT8 = 0x0003, - UINT16 = 0x0004, - UINT32 = 0x0005, - - BOOL = 0x0006, - - FIX32 = 0x0007, - - FRAME = 0x0008, - - STR32 = 0x0009, - STR64 = 0x000a, - STR128 = 0x000b, - STR255 = 0x000c, - HANDLE = 0x000f - } - - #endregion - - - /////////////////////////////////////////////////////////////////////////////// - // Capability Constants... - /////////////////////////////////////////////////////////////////////////////// - #region Capability Constants... - - /// - /// CAP_ALARMS values - /// - public enum TWAL : ushort - { - ALARM = 0, - FEEDERERROR = 1, - FEEDERWARNING = 2, - BARCODE = 3, - DOUBLEFEED = 4, - JAM = 5, - PATCHCODE = 6, - POWER = 7, - SKEW = 8 - } - - /// - /// ICAP_AUTOSIZE values - /// - public enum TWAS : ushort - { - NONE = 0, - AUTO = 1, - CURRENT = 2 - } - - /// - /// TWEI_BARCODEROTATION values - /// - public enum TWBCOR : ushort - { - ROT0 = 0, - ROT90 = 1, - ROT180 = 2, - ROT270 = 3, - ROTX = 4 - } - - /// - /// ICAP_BARCODESEARCHMODE values - /// - public enum TWBD : ushort - { - HORZ = 0, - VERT = 1, - HORZVERT = 2, - VERTHORZ = 3 - } - - /// - /// ICAP_BITORDER values - /// - public enum TWBO : ushort - { - LSBFIRST = 0, - MSBFIRST = 1 - } - - /// - /// ICAP_AUTODISCARDBLANKPAGES values - /// - public enum TWBP : short - { - DISABLE = -2, - AUTO = -1 - } - - /// - /// ICAP_BITDEPTHREDUCTION values - /// - public enum TWBR : ushort - { - THRESHOLD = 0, - HALFTONE = 1, - CUSTHALFTONE = 2, - DIFFUSION = 3, - DYNAMICTHRESHOLD = 4 - } - - /// - /// ICAP_SUPPORTEDBARCODETYPES and TWEI_BARCODETYPE values - /// - public enum TWBT : ushort - { - X3OF9 = 0, // 3OF9 in H - X2OF5INTERLEAVED = 1, // 2OF5INTERLEAVED in H - X2OF5NONINTERLEAVED = 2, // 2OF5NONINTERLEAVED in H - CODE93 = 3, - CODE128 = 4, - UCC128 = 5, - CODABAR = 6, - UPCA = 7, - UPCE = 8, - EAN8 = 9, - EAN13 = 10, - POSTNET = 11, - PDF417 = 12, - X2OF5INDUSTRIAL = 13, // 2OF5INDUSTRIAL in H - X2OF5MATRIX = 14, // 2OF5MATRIX in H - X2OF5DATALOGIC = 15, // 2OF5DATALOGIC in H - X2OF5IATA = 16, // 2OF5IATA in H - X3OF9FULLASCII = 17, // 3OF9FULLASCII in H - CODABARWITHSTARTSTOP = 18, - MAXICODE = 19, - QRCODE = 20 - } - - /// - /// ICAP_COMPRESSION values - /// - public enum TWCP : ushort - { - NONE = 0, - PACKBITS = 1, - GROUP31D = 2, - GROUP31DEOL = 3, - GROUP32D = 4, - GROUP4 = 5, - JPEG = 6, - LZW = 7, - JBIG = 8, - PNG = 9, - RLE4 = 10, - RLE8 = 11, - BITFIELDS = 12, - ZIP = 13, - JPEG2000 = 14 - } - - /// - /// CAP_CAMERASIDE and TWEI_PAGESIDE values - /// - public enum TWCS : ushort - { - BOTH = 0, - TOP = 1, - BOTTOM = 2 - } - - /// - /// CAP_CLEARBUFFERS values - /// - public enum TWCB : ushort - { - AUTO = 0, - CLEAR = 1, - NOCLEAR = 2 - } - - /// - /// CAP_DEVICEEVENT values - /// - public enum TWDE : ushort - { - CUSTOMEVENTS = 0x8000, - CHECKAUTOMATICCAPTURE = 0, - CHECKBATTERY = 1, - CHECKDEVICEONLINE = 2, - CHECKFLASH = 3, - CHECKPOWERSUPPLY = 4, - CHECKRESOLUTION = 5, - DEVICEADDED = 6, - DEVICEOFFLINE = 7, - DEVICEREADY = 8, - DEVICEREMOVED = 9, - IMAGECAPTURED = 10, - IMAGEDELETED = 11, - PAPERDOUBLEFEED = 12, - PAPERJAM = 13, - LAMPFAILURE = 14, - POWERSAVE = 15, - POWERSAVENOTIFY = 16 - } - - /// - /// TW_PASSTHRU.Direction values - /// - public enum TWDR : ushort - { - GET = 1, - SET = 2 - } - - /// - /// TWEI_DESKEWSTATUS values - /// - public enum TWDSK : ushort - { - SUCCESS = 0, - REPORTONLY = 1, - FAIL = 2, - DISABLED = 3 - } - - /// - /// CAP_DUPLEX values - /// - public enum TWDX : ushort - { - NONE = 0, - X1PASSDUPLEX = 1, // 1PASSDUPLEX in H - X2PASSDUPLEX = 2 // 2PASSDUPLEX in H - } - - /// - /// CAP_FEEDERALIGNMENT values - /// - public enum TWFA : ushort - { - NONE = 0, - LEFT = 1, - CENTER = 2, - RIGHT = 3 - } - - /// - /// ICAP_FEEDERTYPE values - /// - public enum TWFE : ushort - { - GENERAL = 0, - PHOTO = 1 - } - - /// - /// ICAP_IMAGEFILEFORMAT values - /// - public enum TWFF : ushort - { - TIFF = 0, - PICT = 1, - BMP = 2, - XBM = 3, - JFIF = 4, - FPX = 5, - TIFFMULTI = 6, - PNG = 7, - SPIFF = 8, - EXIF = 9, - PDF = 10, - JP2 = 11, - JPX = 13, - DEJAVU = 14, - PDFA = 15, - PDFA2 = 16, - PDFRASTER = 17, - - // KODAK - RAW = 0x8001, - RAWBMP = 0x8002 - } - - /// - /// ICAP_FLASHUSED2 values - /// - public enum TWFL : ushort - { - NONE = 0, - OFF = 1, - ON = 2, - AUTO = 3, - REDEYE = 4 - } - - /// - /// CAP_FEEDERORDER values - /// - public enum TWFO : ushort - { - FIRSTPAGEFIRST = 0, - LASTPAGEFIRST = 1 - } - - /// - /// CAP_FEEDERPOCKET values - /// - public enum TWFP : ushort - { - POCKETERROR = 0, - POCKET1 = 1, - POCKET2 = 2, - POCKET3 = 3, - POCKET4 = 4, - POCKET5 = 5, - POCKET6 = 6, - POCKET7 = 7, - POCKET8 = 8, - POCKET9 = 9, - POCKET10 = 10, - POCKET11 = 11, - POCKET12 = 12, - POCKET13 = 13, - POCKET14 = 14, - POCKET15 = 15, - POCKET16 = 16 - } - - /// - /// ICAP_FLIPROTATION values - /// - public enum TWFR : ushort - { - BOOK = 0, - FANFOLD = 1 - } - - /// - /// ICAP_FILTER values - /// - public enum TWFT : ushort - { - RED = 0, - GREEN = 1, - BLUE = 2, - NONE = 3, - WHITE = 4, - CYAN = 5, - MAGENTA = 6, - YELLOW = 7, - BLACK = 8 - } - - /// - /// TW_FILESYSTEM.FileType values - /// - public enum TWFY : ushort - { - CAMERA = 0, - CAMERATOP = 1, - CAMERABOTTOM = 2, - CAMERAPREVIEW = 3, - DOMAIN = 4, - HOST = 5, - DIRECTORY = 6, - IMAGE = 7, - UNKNOWN = 8 - } - - /// - /// CAP_IAFIELD*_LEVEL values - /// - public enum TWIA : ushort - { - UNUSED = 0, - FIXED = 1, - LEVEL1 = 2, - LEVEL2 = 3, - LEVEL3 = 4, - LEVEL4 = 5 - } - - /// - /// ICAP_ICCPROFILE values - /// - public enum TWIC : ushort - { - NONE = 0, - LINK = 1, - EMBED = 2 - } - - /// - /// ICAP_IMAGEFILTER values - /// - public enum TWIF : ushort - { - NONE = 0, - AUTO = 1, - LOWPASS = 2, - BANDPASS = 3, - HIGHPASS = 4, - TEXT = BANDPASS, - FINELINE = HIGHPASS - } - - /// - /// ICAP_IMAGEMERGE values - /// - public enum TWIM : ushort - { - NONE = 0, - FRONTONTOP = 1, - FRONTONBOTTOM = 2, - FRONTONLEFT = 3, - FRONTONRIGHT = 4 - } - - /// - /// CAP_JOBCONTROL values - /// - public enum TWJC : ushort - { - NONE = 0, - JSIC = 1, - JSIS = 2, - JSXC = 3, - JSXS = 4 - } - - /// - /// ICAP_JPEGQUALITY values - /// - public enum TWJQ : short - { - UNKNOWN = -4, - LOW = -3, - MEDIUM = -2, - HIGH = -1 - } - - /// - /// ICAP_LIGHTPATH values - /// - public enum TWLP : ushort - { - REFLECTIVE = 0, - TRANSMISSIVE = 1 - } - - /// - /// ICAP_LIGHTSOURCE values - /// - public enum TWLS : ushort - { - RED = 0, - GREEN = 1, - BLUE = 2, - NONE = 3, - WHITE = 4, - UV = 5, - IR = 6 - } - - /// - /// TWEI_MAGTYPE values - /// - public enum TWMD : ushort - { - MICR = 0, - RAW = 1, - INVALID = 2 - } - - /// - /// ICAP_NOISEFILTER values - /// - public enum TWNF : ushort - { - NONE = 0, - AUTO = 1, - LONEPIXEL = 2, - MAJORITYRULE = 3 - } - - /// - /// ICAP_ORIENTATION values - /// - public enum TWOR : ushort - { - ROT0 = 0, - ROT90 = 1, - ROT180 = 2, - ROT270 = 3, - PORTRAIT = ROT0, - LANDSCAPE = ROT270, - AUTO = 4, - AUTOTEXT = 5, - AUTOPICTURE = 6 - } - - /// - /// ICAP_OVERSCAN values - /// - public enum TWOV : ushort - { - NONE = 0, - AUTO = 1, - TOPBOTTOM = 2, - LEFTRIGHT = 3, - ALL = 4 - } - - /// - /// Palette types for TW_PALETTE8 - /// - public enum TWPA : ushort - { - RGB = 0, - GRAY = 1, - CMY = 2 - } - - /// - /// ICAP_PLANARCHUNKY values - /// - public enum TWPC : ushort - { - CHUNKY = 0, - PLANAR = 1 - } - - /// - /// TWEI_PATCHCODE values - /// - public enum TWPCH : ushort - { - PATCH1 = 0, - PATCH2 = 1, - PATCH3 = 2, - PATCH4 = 3, - PATCH6 = 4, - PATCHT = 5 - } - - /// - /// ICAP_PIXELFLAVOR values - /// - public enum TWPF : ushort - { - CHOCOLATE = 0, - VANILLA = 1 - } - - /// - /// CAP_PRINTERMODE values - /// - public enum TWPM : ushort - { - SINGLESTRING = 0, - MULTISTRING = 1, - COMPOUNDSTRING = 2, - IMAGEADDRESSSTRING = 3 - } - - /// - /// CAP_PRINTER values - /// - public enum TWPR : ushort - { - IMPRINTERTOPBEFORE = 0, - IMPRINTERTOPAFTER = 1, - IMPRINTERBOTTOMBEFORE = 2, - IMPRINTERBOTTOMAFTER = 3, - ENDORSERTOPBEFORE = 4, - ENDORSERTOPAFTER = 5, - ENDORSERBOTTOMBEFORE = 6, - ENDORSERBOTTOMAFTER = 7 - } - - /// - /// CAP_PRINTERFONTSTYLE Added 2.3 (TWPF in H) - /// - public enum TWPFS : ushort - { - NORMAL = 0, - BOLD = 1, - ITALIC = 2, - LARGESIZE = 3, - SMALLSIZE = 4 - } - - /// - /// CAP_PRINTERINDEXTRIGGER Added 2.3 - /// - public enum TWCT : ushort - { - PAGE = 0, - PATCH1 = 1, - PATCH2 = 2, - PATCH3 = 3, - PATCH4 = 4, - PATCHT = 5, - PATCH6 = 6 - } - - /// - /// CAP_POWERSUPPLY values - /// - public enum TWPS : ushort - { - EXTERNAL = 0, - BATTERY = 1 - } - - /// - /// ICAP_PIXELTYPE values (PT_ means Pixel Type) - /// - public enum TWPT : ushort - { - BW = 0, - GRAY = 1, - RGB = 2, - PALETTE = 3, - CMY = 4, - CMYK = 5, - YUV = 6, - YUVK = 7, - CIEXYZ = 8, - LAB = 9, - SRGB = 10, - SCRGB = 11, - INFRARED = 16 - } - - /// - /// CAP_SEGMENTED values - /// - public enum TWSG : ushort - { - NONE = 0, - AUTO = 1, - MANUAL = 2 - } - - /// - /// ICAP_FILMTYPE values - /// - public enum TWFM : ushort - { - POSITIVE = 0, - NEGATIVE = 1 - } - - /// - /// CAP_DOUBLEFEEDDETECTION values - /// - public enum TWDF : ushort - { - ULTRASONIC = 0, - BYLENGTH = 1, - INFRARED = 2 - } - - /// - /// CAP_DOUBLEFEEDDETECTIONSENSITIVITY values - /// - public enum TWUS : ushort - { - LOW = 0, - MEDIUM = 1, - HIGH = 2 - } - - /// - /// CAP_DOUBLEFEEDDETECTIONRESPONSE values - /// - public enum TWDP : ushort - { - STOP = 0, - STOPANDWAIT = 1, - SOUND = 2, - DONOTIMPRINT = 3 - } - - /// - /// ICAP_MIRROR values - /// - public enum TWMR : ushort - { - NONE = 0, - VERTICAL = 1, - HORIZONTAL = 2 - } - - /// - /// ICAP_JPEGSUBSAMPLING values - /// - public enum TWJS : ushort - { - X444YCBCR = 0, // 444YCBCR in H - X444RGB = 1, // 444RGB in H - X422 = 2, // 422 in H - X421 = 3, // 421 in H - X411 = 4, // 411 in H - X420 = 5, // 420 in H - X410 = 6, // 410 in H - X311 = 7 // 311 in H - } - - /// - /// CAP_PAPERHANDLING values - /// - public enum TWPH : ushort - { - NORMAL = 0, - FRAGILE = 1, - THICK = 2, - TRIFOLD = 3, - PHOTOGRAPH = 4 - } - - /// - /// CAP_INDICATORSMODE values - /// - public enum TWCI : ushort - { - INFO = 0, - WARNING = 1, - ERROR = 2, - WARMUP = 3 - } - - /// - /// ICAP_SUPPORTEDSIZES values (SS_ means Supported Sizes) - /// - public enum TWSS : ushort - { - NONE = 0, - A4 = 1, - JISB5 = 2, - USLETTER = 3, - USLEGAL = 4, - A5 = 5, - ISOB4 = 6, - ISOB6 = 7, - USLEDGER = 9, - USEXECUTIVE = 10, - A3 = 11, - ISOB3 = 12, - A6 = 13, - C4 = 14, - C5 = 15, - C6 = 16, - X4A0 = 17, // 4A0 in H - X2A0 = 18, // 2A0 in H - A0 = 19, - A1 = 20, - A2 = 21, - A7 = 22, - A8 = 23, - A9 = 24, - A10 = 25, - ISOB0 = 26, - ISOB1 = 27, - ISOB2 = 28, - ISOB5 = 29, - ISOB7 = 30, - ISOB8 = 31, - ISOB9 = 32, - ISOB10 = 33, - JISB0 = 34, - JISB1 = 35, - JISB2 = 36, - JISB3 = 37, - JISB4 = 38, - JISB6 = 39, - JISB7 = 40, - JISB8 = 41, - JISB9 = 42, - JISB10 = 43, - C0 = 44, - C1 = 45, - C2 = 46, - C3 = 47, - C7 = 48, - C8 = 49, - C9 = 50, - C10 = 51, - USSTATEMENT = 52, - BUSINESSCARD = 53, - MAXSIZE = 54 - } - - /// - /// ICAP_XFERMECH values (SX_ means Setup XFer) - /// - public enum TWSX : ushort - { - NATIVE = 0, - FILE = 1, - MEMORY = 2, - MEMFILE = 4 - } - - /// - /// ICAP_UNITS values (UN_ means UNits) - /// - public enum TWUN : ushort - { - INCHES = 0, - CENTIMETERS = 1, - PICAS = 2, - POINTS = 3, - TWIPS = 4, - PIXELS = 5, - MILLIMETERS = 6 - } - - /// - /// Country Constants - /// - public enum TWCY : ushort - { - AFGHANISTAN = 1001, - ALGERIA = 213, - AMERICANSAMOA = 684, - ANDORRA = 33, - ANGOLA = 1002, - ANGUILLA = 8090, - ANTIGUA = 8091, - ARGENTINA = 54, - ARUBA = 297, - ASCENSIONI = 247, - AUSTRALIA = 61, - AUSTRIA = 43, - BAHAMAS = 8092, - BAHRAIN = 973, - BANGLADESH = 880, - BARBADOS = 8093, - BELGIUM = 32, - BELIZE = 501, - BENIN = 229, - BERMUDA = 8094, - BHUTAN = 1003, - BOLIVIA = 591, - BOTSWANA = 267, - BRITAIN = 6, - BRITVIRGINIS = 8095, - BRAZIL = 55, - BRUNEI = 673, - BULGARIA = 359, - BURKINAFASO = 1004, - BURMA = 1005, - BURUNDI = 1006, - CAMAROON = 237, - CANADA = 2, - CAPEVERDEIS = 238, - CAYMANIS = 8096, - CENTRALAFREP = 1007, - CHAD = 1008, - CHILE = 56, - CHINA = 86, - CHRISTMASIS = 1009, - COCOSIS = 1009, - COLOMBIA = 57, - COMOROS = 1010, - CONGO = 1011, - COOKIS = 1012, - COSTARICA = 506, - CUBA = 5, - CYPRUS = 357, - CZECHOSLOVAKIA = 42, - DENMARK = 45, - DJIBOUTI = 1013, - DOMINICA = 8097, - DOMINCANREP = 8098, - EASTERIS = 1014, - ECUADOR = 593, - EGYPT = 20, - ELSALVADOR = 503, - EQGUINEA = 1015, - ETHIOPIA = 251, - FALKLANDIS = 1016, - FAEROEIS = 298, - FIJIISLANDS = 679, - FINLAND = 358, - FRANCE = 33, - FRANTILLES = 596, - FRGUIANA = 594, - FRPOLYNEISA = 689, - FUTANAIS = 1043, - GABON = 241, - GAMBIA = 220, - GERMANY = 49, - GHANA = 233, - GIBRALTER = 350, - GREECE = 30, - GREENLAND = 299, - GRENADA = 8099, - GRENEDINES = 8015, - GUADELOUPE = 590, - GUAM = 671, - GUANTANAMOBAY = 5399, - GUATEMALA = 502, - GUINEA = 224, - GUINEABISSAU = 1017, - GUYANA = 592, - HAITI = 509, - HONDURAS = 504, - HONGKONG = 852, - HUNGARY = 36, - ICELAND = 354, - INDIA = 91, - INDONESIA = 62, - IRAN = 98, - IRAQ = 964, - IRELAND = 353, - ISRAEL = 972, - ITALY = 39, - IVORYCOAST = 225, - JAMAICA = 8010, - JAPAN = 81, - JORDAN = 962, - KENYA = 254, - KIRIBATI = 1018, - KOREA = 82, - KUWAIT = 965, - LAOS = 1019, - LEBANON = 1020, - LIBERIA = 231, - LIBYA = 218, - LIECHTENSTEIN = 41, - LUXENBOURG = 352, - MACAO = 853, - MADAGASCAR = 1021, - MALAWI = 265, - MALAYSIA = 60, - MALDIVES = 960, - MALI = 1022, - MALTA = 356, - MARSHALLIS = 692, - MAURITANIA = 1023, - MAURITIUS = 230, - MEXICO = 3, - MICRONESIA = 691, - MIQUELON = 508, - MONACO = 33, - MONGOLIA = 1024, - MONTSERRAT = 8011, - MOROCCO = 212, - MOZAMBIQUE = 1025, - NAMIBIA = 264, - NAURU = 1026, - NEPAL = 977, - NETHERLANDS = 31, - NETHANTILLES = 599, - NEVIS = 8012, - NEWCALEDONIA = 687, - NEWZEALAND = 64, - NICARAGUA = 505, - NIGER = 227, - NIGERIA = 234, - NIUE = 1027, - NORFOLKI = 1028, - NORWAY = 47, - OMAN = 968, - PAKISTAN = 92, - PALAU = 1029, - PANAMA = 507, - PARAGUAY = 595, - PERU = 51, - PHILLIPPINES = 63, - PITCAIRNIS = 1030, - PNEWGUINEA = 675, - POLAND = 48, - PORTUGAL = 351, - QATAR = 974, - REUNIONI = 1031, - ROMANIA = 40, - RWANDA = 250, - SAIPAN = 670, - SANMARINO = 39, - SAOTOME = 1033, - SAUDIARABIA = 966, - SENEGAL = 221, - SEYCHELLESIS = 1034, - SIERRALEONE = 1035, - SINGAPORE = 65, - SOLOMONIS = 1036, - SOMALI = 1037, - SOUTHAFRICA = 27, - SPAIN = 34, - SRILANKA = 94, - STHELENA = 1032, - STKITTS = 8013, - STLUCIA = 8014, - STPIERRE = 508, - STVINCENT = 8015, - SUDAN = 1038, - SURINAME = 597, - SWAZILAND = 268, - SWEDEN = 46, - SWITZERLAND = 41, - SYRIA = 1039, - TAIWAN = 886, - TANZANIA = 255, - THAILAND = 66, - TOBAGO = 8016, - TOGO = 228, - TONGAIS = 676, - TRINIDAD = 8016, - TUNISIA = 216, - TURKEY = 90, - TURKSCAICOS = 8017, - TUVALU = 1040, - UGANDA = 256, - USSR = 7, - UAEMIRATES = 971, - UNITEDKINGDOM = 44, - USA = 1, - URUGUAY = 598, - VANUATU = 1041, - VATICANCITY = 39, - VENEZUELA = 58, - WAKE = 1042, - WALLISIS = 1043, - WESTERNSAHARA = 1044, - WESTERNSAMOA = 1045, - YEMEN = 1046, - YUGOSLAVIA = 38, - ZAIRE = 243, - ZAMBIA = 260, - ZIMBABWE = 263, - ALBANIA = 355, - ARMENIA = 374, - AZERBAIJAN = 994, - BELARUS = 375, - BOSNIAHERZGO = 387, - CAMBODIA = 855, - CROATIA = 385, - CZECHREPUBLIC = 420, - DIEGOGARCIA = 246, - ERITREA = 291, - ESTONIA = 372, - GEORGIA = 995, - LATVIA = 371, - LESOTHO = 266, - LITHUANIA = 370, - MACEDONIA = 389, - MAYOTTEIS = 269, - MOLDOVA = 373, - MYANMAR = 95, - NORTHKOREA = 850, - PUERTORICO = 787, - RUSSIA = 7, - SERBIA = 381, - SLOVAKIA = 421, - SLOVENIA = 386, - SOUTHKOREA = 82, - UKRAINE = 380, - USVIRGINIS = 340, - VIETNAM = 84 - } - - /// - /// Language Constants - /// - public enum TWLG : short - { - USERLOCALE = -1, - DAN = 0, - DUT = 1, - ENG = 2, - FCF = 3, - FIN = 4, - FRN = 5, - GER = 6, - ICE = 7, - ITN = 8, - NOR = 9, - POR = 10, - SPA = 11, - SWE = 12, - USA = 13, - AFRIKAANS = 14, - ALBANIA = 15, - ARABIC = 16, - ARABIC_ALGERIA = 17, - ARABIC_BAHRAIN = 18, - ARABIC_EGYPT = 19, - ARABIC_IRAQ = 20, - ARABIC_JORDAN = 21, - ARABIC_KUWAIT = 22, - ARABIC_LEBANON = 23, - ARABIC_LIBYA = 24, - ARABIC_MOROCCO = 25, - ARABIC_OMAN = 26, - ARABIC_QATAR = 27, - ARABIC_SAUDIARABIA = 28, - ARABIC_SYRIA = 29, - ARABIC_TUNISIA = 30, - ARABIC_UAE = 31, - ARABIC_YEMEN = 32, - BASQUE = 33, - BYELORUSSIAN = 34, - BULGARIAN = 35, - CATALAN = 36, - CHINESE = 37, - CHINESE_HONGKONG = 38, - CHINESE_PRC = 39, - CHINESE_SINGAPORE = 40, - CHINESE_SIMPLIFIED = 41, - CHINESE_TAIWAN = 42, - CHINESE_TRADITIONAL = 43, - CROATIA = 44, - CZECH = 45, - DANISH = DAN, - DUTCH = DUT, - DUTCH_BELGIAN = 46, - ENGLISH = ENG, - ENGLISH_AUSTRALIAN = 47, - ENGLISH_CANADIAN = 48, - ENGLISH_IRELAND = 49, - ENGLISH_NEWZEALAND = 50, - ENGLISH_SOUTHAFRICA = 51, - ENGLISH_UK = 52, - ENGLISH_USA = USA, - ESTONIAN = 53, - FAEROESE = 54, - FARSI = 55, - FINNISH = FIN, - FRENCH = FRN, - FRENCH_BELGIAN = 56, - FRENCH_CANADIAN = FCF, - FRENCH_LUXEMBOURG = 57, - FRENCH_SWISS = 58, - GERMAN = GER, - GERMAN_AUSTRIAN = 59, - GERMAN_LUXEMBOURG = 60, - GERMAN_LIECHTENSTEIN = 61, - GERMAN_SWISS = 62, - GREEK = 63, - HEBREW = 64, - HUNGARIAN = 65, - ICELANDIC = ICE, - INDONESIAN = 66, - ITALIAN = ITN, - ITALIAN_SWISS = 67, - JAPANESE = 68, - KOREAN = 69, - KOREAN_JOHAB = 70, - LATVIAN = 71, - LITHUANIAN = 72, - NORWEGIAN = NOR, - NORWEGIAN_BOKMAL = 73, - NORWEGIAN_NYNORSK = 74, - POLISH = 75, - PORTUGUESE = POR, - PORTUGUESE_BRAZIL = 76, - ROMANIAN = 77, - RUSSIAN = 78, - SERBIAN_LATIN = 79, - SLOVAK = 80, - SLOVENIAN = 81, - SPANISH = TWLG.SPA, - SPANISH_MEXICAN = 82, - SPANISH_MODERN = 83, - SWEDISH = TWLG.SWE, - THAI = 84, - TURKISH = 85, - UKRANIAN = 86, - ASSAMESE = 87, - BENGALI = 88, - BIHARI = 89, - BODO = 90, - DOGRI = 91, - GUJARATI = 92, - HARYANVI = 93, - HINDI = 94, - KANNADA = 95, - KASHMIRI = 96, - MALAYALAM = 97, - MARATHI = 98, - MARWARI = 99, - MEGHALAYAN = 100, - MIZO = 101, - NAGA = 102, - ORISSI = 103, - PUNJABI = 104, - PUSHTU = 105, - SERBIAN_CYRILLIC = 106, - SIKKIMI = 107, - SWEDISH_FINLAND = 108, - TAMIL = 109, - TELUGU = 110, - TRIPURI = 111, - URDU = 112, - VIETNAMESE = 113 - //NOTE: when adding to this list, also update Language->Set() - } - - #endregion - - - /////////////////////////////////////////////////////////////////////////////// - // Data Groups... - /////////////////////////////////////////////////////////////////////////////// - #region Data Groups... - - /// - /// Data Groups... - /// - [Flags] - public enum DG : uint - { - CONTROL = 0x1, - IMAGE = 0x2, - AUDIO = 0x4, - - // More Data Functionality may be added in the future. - // These are for items that need to be determined before DS is opened. - // NOTE: Supported Functionality constants must be powers of 2 as they are - // used as bitflags when Application asks DSM to present a list of DSs. - // to support backward capability the App and DS will not use the fields - DSM2 = 0x10000000, - APP2 = 0x20000000, - DS2 = 0x40000000, - MASK = 0xFFFF - } - - #endregion - - - /////////////////////////////////////////////////////////////////////////////// - // Data Argument Types... - /////////////////////////////////////////////////////////////////////////////// - #region Data Argument Types... - - /// - /// Data Argument Types... - /// - public enum DAT : ushort - { - // NULL and Custom Base... - NULL = 0x0, - CUSTOM = 0x8000, - - // Data Argument Types for the DG_CONTROL Data Group. - CAPABILITY = 0x1, - EVENT = 0x2, - IDENTITY = 0x3, - PARENT = 0x4, - PENDINGXFERS = 0x5, - SETUPMEMXFER = 0x6, - SETUPFILEXFER = 0x7, - STATUS = 0x8, - USERINTERFACE = 0x9, - XFERGROUP = 0xa, - CUSTOMDSDATA = 0xc, - DEVICEEVENT = 0xd, - FILESYSTEM = 0xe, - PASSTHRU = 0xf, - CALLBACK = 0x10, - STATUSUTF8 = 0x11, - CALLBACK2 = 0x12, - METRICS = 0x13, - TWAINDIRECT = 0x14, - - // Data Argument Types for the DG_IMAGE Data Group. - IMAGEINFO = 0x0101, - IMAGELAYOUT = 0x0102, - IMAGEMEMXFER = 0x0103, - IMAGENATIVEXFER = 0x0104, - IMAGEFILEXFER = 0x105, - CIECOLOR = 0x106, - GRAYRESPONSE = 0x107, - RGBRESPONSE = 0x108, - JPEGCOMPRESSION = 0x109, - PALETTE8 = 0x10a, - EXTIMAGEINFO = 0x10b, - FILTER = 0x10c, - - /* Data Argument Types for the DG_AUDIO Data Group. */ - AUDIOFILEXFER = 0x201, - AUDIOINFO = 0x202, - AUDIONATIVEXFER = 0x203, - - /* misplaced */ - ICCPROFILE = 0x401, - IMAGEMEMFILEXFER = 0x402, - ENTRYPOINT = 0x403 - } - - #endregion - - - /////////////////////////////////////////////////////////////////////////////// - // Messages... - /////////////////////////////////////////////////////////////////////////////// - #region Messages... - - /// - /// All message constants are unique. - /// Messages are grouped according to which DATs they are used with. - /// - public enum MSG : ushort - { - // Only used to clear fields... - NULL = 0x0, - - // Generic messages may be used with any of several DATs. - GET = 0x1, - GETCURRENT = 0x2, - GETDEFAULT = 0x3, - GETFIRST = 0x4, - GETNEXT = 0x5, - SET = 0x6, - RESET = 0x7, - QUERYSUPPORT = 0x8, - GETHELP = 0x9, - GETLABEL = 0xa, - GETLABELENUM = 0xb, - SETCONSTRAINT = 0xc, - - // Messages used with DAT_NULL. - XFERREADY = 0x101, - CLOSEDSREQ = 0x102, - CLOSEDSOK = 0x103, - DEVICEEVENT = 0x104, - - // Messages used with a pointer to DAT_PARENT data. - OPENDSM = 0x301, - CLOSEDSM = 0x302, - - // Messages used with a pointer to a DAT_IDENTITY structure. - OPENDS = 0x401, - CLOSEDS = 0x402, - USERSELECT = 0x403, - - // Messages used with a pointer to a DAT_USERINTERFACE structure. - DISABLEDS = 0x501, - ENABLEDS = 0x502, - ENABLEDSUIONLY = 0x503, - - // Messages used with a pointer to a DAT_EVENT structure. - PROCESSEVENT = 0x601, - - // Messages used with a pointer to a DAT_PENDINGXFERS structure - ENDXFER = 0x701, - STOPFEEDER = 0x702, - - // Messages used with a pointer to a DAT_FILESYSTEM structure - CHANGEDIRECTORY = 0x0801, - CREATEDIRECTORY = 0x0802, - DELETE = 0x0803, - FORMATMEDIA = 0x0804, - GETCLOSE = 0x0805, - GETFIRSTFILE = 0x0806, - GETINFO = 0x0807, - GETNEXTFILE = 0x0808, - RENAME = 0x0809, - COPY = 0x080A, - AUTOMATICCAPTUREDIRECTORY = 0x080B, - - // Messages used with a pointer to a DAT_PASSTHRU structure - PASSTHRU = 0x0901, - - // used with DAT_CALLBACK - REGISTER_CALLBACK = 0x0902, - - // used with DAT_CAPABILITY - RESETALL = 0x0A01, - - // used with DAT_TWAINDIRECT - SETTASK = 0x0B01, - } - - #endregion - - - /////////////////////////////////////////////////////////////////////////////// - // Capabilities... - /////////////////////////////////////////////////////////////////////////////// - #region Capabilities... - - /// - /// The naming convention is a little awkward, but it allows us to - /// achieve a unified capability type... - /// - public enum CAP : ushort - { - // Base of custom capabilities. - CAP_CUSTOMBASE = 0x8000, - - /* all data sources are REQUIRED to support these caps */ - CAP_XFERCOUNT = 0x0001, - - /* image data sources are REQUIRED to support these caps */ - ICAP_COMPRESSION = 0x0100, - ICAP_PIXELTYPE = 0x0101, - ICAP_UNITS = 0x0102, - ICAP_XFERMECH = 0x0103, - - // all data sources MAY support these caps. - CAP_AUTHOR = 0x1000, - CAP_CAPTION = 0x1001, - CAP_FEEDERENABLED = 0x1002, - CAP_FEEDERLOADED = 0x1003, - CAP_TIMEDATE = 0x1004, - CAP_SUPPORTEDCAPS = 0x1005, - CAP_EXTENDEDCAPS = 0x1006, - CAP_AUTOFEED = 0x1007, - CAP_CLEARPAGE = 0x1008, - CAP_FEEDPAGE = 0x1009, - CAP_REWINDPAGE = 0x100a, - CAP_INDICATORS = 0x100b, - CAP_PAPERDETECTABLE = 0x100d, - CAP_UICONTROLLABLE = 0x100e, - CAP_DEVICEONLINE = 0x100f, - CAP_AUTOSCAN = 0x1010, - CAP_THUMBNAILSENABLED = 0x1011, - CAP_DUPLEX = 0x1012, - CAP_DUPLEXENABLED = 0x1013, - CAP_ENABLEDSUIONLY = 0x1014, - CAP_CUSTOMDSDATA = 0x1015, - CAP_ENDORSER = 0x1016, - CAP_JOBCONTROL = 0x1017, - CAP_ALARMS = 0x1018, - CAP_ALARMVOLUME = 0x1019, - CAP_AUTOMATICCAPTURE = 0x101a, - CAP_TIMEBEFOREFIRSTCAPTURE = 0x101b, - CAP_TIMEBETWEENCAPTURES = 0x101c, - CAP_CLEARBUFFERS = 0x101d, - CAP_MAXBATCHBUFFERS = 0x101e, - CAP_DEVICETIMEDATE = 0x101f, - CAP_POWERSUPPLY = 0x1020, - CAP_CAMERAPREVIEWUI = 0x1021, - CAP_DEVICEEVENT = 0x1022, - CAP_SERIALNUMBER = 0x1024, - CAP_PRINTER = 0x1026, - CAP_PRINTERENABLED = 0x1027, - CAP_PRINTERINDEX = 0x1028, - CAP_PRINTERMODE = 0x1029, - CAP_PRINTERSTRING = 0x102a, - CAP_PRINTERSUFFIX = 0x102b, - CAP_LANGUAGE = 0x102c, - CAP_FEEDERALIGNMENT = 0x102d, - CAP_FEEDERORDER = 0x102e, - CAP_REACQUIREALLOWED = 0x1030, - CAP_BATTERYMINUTES = 0x1032, - CAP_BATTERYPERCENTAGE = 0x1033, - CAP_CAMERASIDE = 0x1034, - CAP_SEGMENTED = 0x1035, - CAP_CAMERAENABLED = 0x1036, - CAP_CAMERAORDER = 0x1037, - CAP_MICRENABLED = 0x1038, - CAP_FEEDERPREP = 0x1039, - CAP_FEEDERPOCKET = 0x103a, - CAP_AUTOMATICSENSEMEDIUM = 0x103b, - CAP_CUSTOMINTERFACEGUID = 0x103c, - CAP_SUPPORTEDCAPSSEGMENTUNIQUE = 0x103d, - CAP_SUPPORTEDDATS = 0x103e, - CAP_DOUBLEFEEDDETECTION = 0x103f, - CAP_DOUBLEFEEDDETECTIONLENGTH = 0x1040, - CAP_DOUBLEFEEDDETECTIONSENSITIVITY = 0x1041, - CAP_DOUBLEFEEDDETECTIONRESPONSE = 0x1042, - CAP_PAPERHANDLING = 0x1043, - CAP_INDICATORSMODE = 0x1044, - CAP_PRINTERVERTICALOFFSET = 0x1045, - CAP_POWERSAVETIME = 0x1046, - CAP_PRINTERCHARROTATION = 0x1047, - CAP_PRINTERFONTSTYLE = 0x1048, - CAP_PRINTERINDEXLEADCHAR = 0x1049, - CAP_PRINTERINDEXMAXVALUE = 0x104A, - CAP_PRINTERINDEXNUMDIGITS = 0x104B, - CAP_PRINTERINDEXSTEP = 0x104C, - CAP_PRINTERINDEXTRIGGER = 0x104D, - CAP_PRINTERSTRINGPREVIEW = 0x104E, - CAP_SHEETCOUNT = 0x104F, - CAP_IMAGEADDRESSENABLED = 0x1050, - CAP_IAFIELDA_LEVEL = 0x1051, - CAP_IAFIELDB_LEVEL = 0x1052, - CAP_IAFIELDC_LEVEL = 0x1053, - CAP_IAFIELDD_LEVEL = 0x1054, - CAP_IAFIELDE_LEVEL = 0x1055, - CAP_IAFIELDA_PRINTFORMAT = 0x1056, - CAP_IAFIELDB_PRINTFORMAT = 0x1057, - CAP_IAFIELDC_PRINTFORMAT = 0x1058, - CAP_IAFIELDD_PRINTFORMAT = 0x1059, - CAP_IAFIELDE_PRINTFORMAT = 0x105A, - CAP_IAFIELDA_VALUE = 0x105B, - CAP_IAFIELDB_VALUE = 0x105C, - CAP_IAFIELDC_VALUE = 0x105D, - CAP_IAFIELDD_VALUE = 0x105E, - CAP_IAFIELDE_VALUE = 0x105F, - CAP_IAFIELDA_LASTPAGE = 0x1060, - CAP_IAFIELDB_LASTPAGE = 0x1061, - CAP_IAFIELDC_LASTPAGE = 0x1062, - CAP_IAFIELDD_LASTPAGE = 0x1063, - CAP_IAFIELDE_LASTPAGE = 0x1064, - - // image data sources MAY support these caps. - ICAP_AUTOBRIGHT = 0x1100, - ICAP_BRIGHTNESS = 0x1101, - ICAP_CONTRAST = 0x1103, - ICAP_CUSTHALFTONE = 0x1104, - ICAP_EXPOSURETIME = 0x1105, - ICAP_FILTER = 0x1106, - ICAP_FLASHUSED = 0x1107, - ICAP_GAMMA = 0x1108, - ICAP_HALFTONES = 0x1109, - ICAP_HIGHLIGHT = 0x110a, - ICAP_IMAGEFILEFORMAT = 0x110c, - ICAP_LAMPSTATE = 0x110d, - ICAP_LIGHTSOURCE = 0x110e, - ICAP_ORIENTATION = 0x1110, - ICAP_PHYSICALWIDTH = 0x1111, - ICAP_PHYSICALHEIGHT = 0x1112, - ICAP_SHADOW = 0x1113, - ICAP_FRAMES = 0x1114, - ICAP_XNATIVERESOLUTION = 0x1116, - ICAP_YNATIVERESOLUTION = 0x1117, - ICAP_XRESOLUTION = 0x1118, - ICAP_YRESOLUTION = 0x1119, - ICAP_MAXFRAMES = 0x111a, - ICAP_TILES = 0x111b, - ICAP_BITORDER = 0x111c, - ICAP_CCITTKFACTOR = 0x111d, - ICAP_LIGHTPATH = 0x111e, - ICAP_PIXELFLAVOR = 0x111f, - ICAP_PLANARCHUNKY = 0x1120, - ICAP_ROTATION = 0x1121, - ICAP_SUPPORTEDSIZES = 0x1122, - ICAP_THRESHOLD = 0x1123, - ICAP_XSCALING = 0x1124, - ICAP_YSCALING = 0x1125, - ICAP_BITORDERCODES = 0x1126, - ICAP_PIXELFLAVORCODES = 0x1127, - ICAP_JPEGPIXELTYPE = 0x1128, - ICAP_TIMEFILL = 0x112a, - ICAP_BITDEPTH = 0x112b, - ICAP_BITDEPTHREDUCTION = 0x112c, - ICAP_UNDEFINEDIMAGESIZE = 0x112d, - ICAP_IMAGEDATASET = 0x112e, - ICAP_EXTIMAGEINFO = 0x112f, - ICAP_MINIMUMHEIGHT = 0x1130, - ICAP_MINIMUMWIDTH = 0x1131, - ICAP_AUTODISCARDBLANKPAGES = 0x1134, - ICAP_FLIPROTATION = 0x1136, - ICAP_BARCODEDETECTIONENABLED = 0x1137, - ICAP_SUPPORTEDBARCODETYPES = 0x1138, - ICAP_BARCODEMAXSEARCHPRIORITIES = 0x1139, - ICAP_BARCODESEARCHPRIORITIES = 0x113a, - ICAP_BARCODESEARCHMODE = 0x113b, - ICAP_BARCODEMAXRETRIES = 0x113c, - ICAP_BARCODETIMEOUT = 0x113d, - ICAP_ZOOMFACTOR = 0x113e, - ICAP_PATCHCODEDETECTIONENABLED = 0x113f, - ICAP_SUPPORTEDPATCHCODETYPES = 0x1140, - ICAP_PATCHCODEMAXSEARCHPRIORITIES = 0x1141, - ICAP_PATCHCODESEARCHPRIORITIES = 0x1142, - ICAP_PATCHCODESEARCHMODE = 0x1143, - ICAP_PATCHCODEMAXRETRIES = 0x1144, - ICAP_PATCHCODETIMEOUT = 0x1145, - ICAP_FLASHUSED2 = 0x1146, - ICAP_IMAGEFILTER = 0x1147, - ICAP_NOISEFILTER = 0x1148, - ICAP_OVERSCAN = 0x1149, - ICAP_AUTOMATICBORDERDETECTION = 0x1150, - ICAP_AUTOMATICDESKEW = 0x1151, - ICAP_AUTOMATICROTATE = 0x1152, - ICAP_JPEGQUALITY = 0x1153, - ICAP_FEEDERTYPE = 0x1154, - ICAP_ICCPROFILE = 0x1155, - ICAP_AUTOSIZE = 0x1156, - ICAP_AUTOMATICCROPUSESFRAME = 0x1157, - ICAP_AUTOMATICLENGTHDETECTION = 0x1158, - ICAP_AUTOMATICCOLORENABLED = 0x1159, - ICAP_AUTOMATICCOLORNONCOLORPIXELTYPE = 0x115a, - ICAP_COLORMANAGEMENTENABLED = 0x115b, - ICAP_IMAGEMERGE = 0x115c, - ICAP_IMAGEMERGEHEIGHTTHRESHOLD = 0x115d, - ICAP_SUPPORTEDEXTIMAGEINFO = 0x115e, - ICAP_FILMTYPE = 0x115f, - ICAP_MIRROR = 0x1160, - ICAP_JPEGSUBSAMPLING = 0x1161, - - // image data sources MAY support these audio caps. - ACAP_XFERMECH = 0x1202 - } - - #endregion - - - /////////////////////////////////////////////////////////////////////////////// - // Extended Image Info Attributes section Added 1.7... - /////////////////////////////////////////////////////////////////////////////// - #region Extended Image Info Attributes section Added 1.7... - - /// - /// Extended Image Info Attributes... - /// - public enum TWEI : ushort - { - BARCODEX = 0x1200, - BARCODEY = 0x1201, - BARCODETEXT = 0x1202, - BARCODETYPE = 0x1203, - DESHADETOP = 0x1204, - DESHADELEFT = 0x1205, - DESHADEHEIGHT = 0x1206, - DESHADEWIDTH = 0x1207, - DESHADESIZE = 0x1208, - SPECKLESREMOVED = 0x1209, - HORZLINEXCOORD = 0x120A, - HORZLINEYCOORD = 0x120B, - HORZLINELENGTH = 0x120C, - HORZLINETHICKNESS = 0x120D, - VERTLINEXCOORD = 0x120E, - VERTLINEYCOORD = 0x120F, - VERTLINELENGTH = 0x1210, - VERTLINETHICKNESS = 0x1211, - PATCHCODE = 0x1212, - ENDORSEDTEXT = 0x1213, - FORMCONFIDENCE = 0x1214, - FORMTEMPLATEMATCH = 0x1215, - FORMTEMPLATEPAGEMATCH = 0x1216, - FORMHORZDOCOFFSET = 0x1217, - FORMVERTDOCOFFSET = 0x1218, - BARCODECOUNT = 0x1219, - BARCODECONFIDENCE = 0x121A, - BARCODEROTATION = 0x121B, - BARCODETEXTLENGTH = 0x121C, - DESHADECOUNT = 0x121D, - DESHADEBLACKCOUNTOLD = 0x121E, - DESHADEBLACKCOUNTNEW = 0x121F, - DESHADEBLACKRLMIN = 0x1220, - DESHADEBLACKRLMAX = 0x1221, - DESHADEWHITECOUNTOLD = 0x1222, - DESHADEWHITECOUNTNEW = 0x1223, - DESHADEWHITERLMIN = 0x1224, - DESHADEWHITERLAVE = 0x1225, - DESHADEWHITERLMAX = 0x1226, - BLACKSPECKLESREMOVED = 0x1227, - WHITESPECKLESREMOVED = 0x1228, - HORZLINECOUNT = 0x1229, - VERTLINECOUNT = 0x122A, - DESKEWSTATUS = 0x122B, - SKEWORIGINALANGLE = 0x122C, - SKEWFINALANGLE = 0x122D, - SKEWCONFIDENCE = 0x122E, - SKEWWINDOWX1 = 0x122F, - SKEWWINDOWY1 = 0x1230, - SKEWWINDOWX2 = 0x1231, - SKEWWINDOWY2 = 0x1232, - SKEWWINDOWX3 = 0x1233, - SKEWWINDOWY3 = 0x1234, - SKEWWINDOWX4 = 0x1235, - SKEWWINDOWY4 = 0x1236, - BOOKNAME = 0x1238, - CHAPTERNUMBER = 0x1239, - DOCUMENTNUMBER = 0x123A, - PAGENUMBER = 0x123B, - CAMERA = 0x123C, - FRAMENUMBER = 0x123D, - FRAME = 0x123E, - PIXELFLAVOR = 0x123F, - ICCPROFILE = 0x1240, - LASTSEGMENT = 0x1241, - SEGMENTNUMBER = 0x1242, - MAGDATA = 0x1243, - MAGTYPE = 0x1244, - PAGESIDE = 0x1245, - FILESYSTEMSOURCE = 0x1246, - IMAGEMERGED = 0x1247, - MAGDATALENGTH = 0x1248, - PAPERCOUNT = 0x1249, - PRINTERTEXT = 0x124A, - TWAINDIRECTMETADATA = 0x124B, - IAFIELDA_VALUE = 0x124C, - IAFIELDB_VALUE = 0x124D, - IAFIELDC_VALUE = 0x124E, - IAFIELDD_VALUE = 0x124F, - IAFIELDE_VALUE = 0x1250, - IALEVEL = 0x1251, - PRINTER = 0x1252, - BARCODETEXT2 = 0x1253, - } - - public enum TWEJ : ushort - { - NONE = 0x0000, - MIDSEPARATOR = 0x0001, - PATCH1 = 0x0002, - PATCH2 = 0x0003, - PATCH3 = 0x0004, - PATCH4 = 0x0005, - PATCH6 = 0x0006, - PATCHT = 0x0007 - } - - #endregion - - - /////////////////////////////////////////////////////////////////////////////// - // Return Codes and Condition Codes section... - /////////////////////////////////////////////////////////////////////////////// - #region Return Codes and Condition Codes section... - - //public enum STS - //{ - // // Custom base (same for TWRC and TWCC)... - // CUSTOMBASE = 0x8000, - - // // Return codes... - // SUCCESS = 0, - // FAILURE = 1, - // CHECKSTATUS = 2, - // CANCEL = 3, - // DSEVENT = 4, - // NOTDSEVENT = 5, - // XFERDONE = 6, - // ENDOFLIST = 7, - // INFONOTSUPPORTED = 8, - // DATANOTAVAILABLE = 9, - // BUSY = 10, - // SCANNERLOCKED = 11, - - // // Condition codes (always associated with TWRC_FAILURE)... - // BUMMER = TwainConst.STSCC + 1, - // LOWMEMORY = TwainConst.STSCC + 2, - // NODS = TwainConst.STSCC + 3, - // MAXCONNECTIONS = TwainConst.STSCC + 4, - // OPERATIONERROR = TwainConst.STSCC + 5, - // BADCAP = TwainConst.STSCC + 6, - // BADPROTOCOL = TwainConst.STSCC + 9, - // BADVALUE = TwainConst.STSCC + 10, - // SEQERROR = TwainConst.STSCC + 11, - // BADDEST = TwainConst.STSCC + 12, - // CAPUNSUPPORTED = TwainConst.STSCC + 13, - // CAPBADOPERATION = TwainConst.STSCC + 14, - // CAPSEQERROR = TwainConst.STSCC + 15, - // DENIED = TwainConst.STSCC + 16, - // FILEEXISTS = TwainConst.STSCC + 17, - // FILENOTFOUND = TwainConst.STSCC + 18, - // NOTEMPTY = TwainConst.STSCC + 19, - // PAPERJAM = TwainConst.STSCC + 20, - // PAPERDOUBLEFEED = TwainConst.STSCC + 21, - // FILEWRITEERROR = TwainConst.STSCC + 22, - // CHECKDEVICEONLINE = TwainConst.STSCC + 23, - // INTERLOCK = TwainConst.STSCC + 24, - // DAMAGEDCORNER = TwainConst.STSCC + 25, - // FOCUSERROR = TwainConst.STSCC + 26, - // DOCTOOLIGHT = TwainConst.STSCC + 27, - // DOCTOODARK = TwainConst.STSCC + 28, - // NOMEDIA = TwainConst.STSCC + 29 - //} - - /// - /// bit patterns: for query the operation that are supported by the data source on a capability - /// Application gets these through DG_CONTROL/DAT_CAPABILITY/MSG_QUERYSUPPORT - /// - [Flags] - public enum TWQC : ushort - { - Unknown = 0, - GET = 0x0001, - SET = 0x0002, - GETDEFAULT = 0x0004, - GETCURRENT = 0x0008, - RESET = 0x0010, - SETCONSTRAINT = 0x0020, - CONSTRAINABLE = 0x0040, - // KODAK additions - /// - /// KODAK ONLY: applies to entire session/machine - /// - MACHINE = 0x1000, - /// - /// KODAK ONLY: applies to Bitonal "cameras" - /// - BITONAL = 0x2000, - /// - /// KODAK ONLY: applies to Color "cameras" - /// - COLOR = 0x3000 - } - - /// - /// The TWAIN States... - /// - public enum STATE - { - S1 = 1, // Nothing loaded or open - S2 = 2, // DSM loaded - S3 = 3, // DSM open - S4 = 4, // Data Source open, programmatic mode (no GUI) - S5 = 5, // GUI up or waiting to transfer first image - S6 = 6, // ready to start transferring image - S7 = 7 // transferring image or transfer done - } - - #endregion - - - /////////////////////////////////////////////////////////////////////////////// - // Language section... - /////////////////////////////////////////////////////////////////////////////// - #region Language section... - - /// - /// Handle encoding between C# and what the DS is currently set to. - /// NOTE: this is static for users of this object do not have to track - /// the encoding (i.e. let cs deal with all of this). This - /// means there is one language for all open DSes, so the last one wins. - /// - public static class Language - { - /// - /// The encoding to use for strings to/from the DS - /// - /// - public static Encoding GetEncoding() - { - return (m_encoding); - } - - /// - /// The current language of the DS - /// - /// - public static void Set(TWLG a_twlg) - { - switch (a_twlg) - { - default: - // NOTE: can only get here if a TWLG was added, but it wasn't added here - m_encoding = Encoding.GetEncoding(1252); - break; - - case TWLG.USERLOCALE: - // NOTE: this should never come back from the DS. only here for completeness - m_encoding = Encoding.GetEncoding(1252); - break; - - case TWLG.THAI: - m_encoding = Encoding.GetEncoding(874); - break; - - case TWLG.JAPANESE: - m_encoding = Encoding.GetEncoding(932); - break; - - case TWLG.CHINESE: - case TWLG.CHINESE_PRC: - case TWLG.CHINESE_SINGAPORE: - case TWLG.CHINESE_SIMPLIFIED: - m_encoding = Encoding.GetEncoding(936); - break; - - case TWLG.KOREAN: - case TWLG.KOREAN_JOHAB: - m_encoding = Encoding.GetEncoding(949); - break; - - case TWLG.CHINESE_HONGKONG: - case TWLG.CHINESE_TAIWAN: - case TWLG.CHINESE_TRADITIONAL: - m_encoding = Encoding.GetEncoding(950); - break; - - case TWLG.ALBANIA: - case TWLG.CROATIA: - case TWLG.CZECH: - case TWLG.HUNGARIAN: - case TWLG.POLISH: - case TWLG.ROMANIAN: - case TWLG.SERBIAN_LATIN: - case TWLG.SLOVAK: - case TWLG.SLOVENIAN: - m_encoding = Encoding.GetEncoding(1250); - break; - - case TWLG.BYELORUSSIAN: - case TWLG.BULGARIAN: - case TWLG.RUSSIAN: - case TWLG.SERBIAN_CYRILLIC: - case TWLG.UKRANIAN: - m_encoding = Encoding.GetEncoding(1251); - break; - - case TWLG.AFRIKAANS: - case TWLG.BASQUE: - case TWLG.CATALAN: - case TWLG.DAN: // DANISH - case TWLG.DUT: // DUTCH - case TWLG.DUTCH_BELGIAN: - case TWLG.ENG: // ENGLISH - case TWLG.ENGLISH_AUSTRALIAN: - case TWLG.ENGLISH_CANADIAN: - case TWLG.ENGLISH_IRELAND: - case TWLG.ENGLISH_NEWZEALAND: - case TWLG.ENGLISH_SOUTHAFRICA: - case TWLG.ENGLISH_UK: - case TWLG.USA: - case TWLG.FAEROESE: - case TWLG.FIN: // FINNISH - case TWLG.FRN: // FRENCH - case TWLG.FRENCH_BELGIAN: - case TWLG.FCF: // FRENCH_CANADIAN - case TWLG.FRENCH_LUXEMBOURG: - case TWLG.FRENCH_SWISS: - case TWLG.GER: // GERMAN - case TWLG.GERMAN_AUSTRIAN: - case TWLG.GERMAN_LIECHTENSTEIN: - case TWLG.GERMAN_LUXEMBOURG: - case TWLG.GERMAN_SWISS: - case TWLG.ICE: // ICELANDIC - case TWLG.INDONESIAN: - case TWLG.ITN: // ITALIAN - case TWLG.ITALIAN_SWISS: - case TWLG.NOR: // NORWEGIAN - case TWLG.NORWEGIAN_BOKMAL: - case TWLG.NORWEGIAN_NYNORSK: - case TWLG.POR: // PORTUGUESE - case TWLG.PORTUGUESE_BRAZIL: - case TWLG.SPA: // SPANISH - case TWLG.SPANISH_MEXICAN: - case TWLG.SPANISH_MODERN: - case TWLG.SWE: // SWEDISH - case TWLG.SWEDISH_FINLAND: - m_encoding = Encoding.GetEncoding(1252); - break; - - case TWLG.GREEK: - m_encoding = Encoding.GetEncoding(1253); - break; - - case TWLG.TURKISH: - m_encoding = Encoding.GetEncoding(1254); - break; - - case TWLG.HEBREW: - m_encoding = Encoding.GetEncoding(1255); - break; - - case TWLG.ARABIC: - case TWLG.ARABIC_ALGERIA: - case TWLG.ARABIC_BAHRAIN: - case TWLG.ARABIC_EGYPT: - case TWLG.ARABIC_IRAQ: - case TWLG.ARABIC_JORDAN: - case TWLG.ARABIC_KUWAIT: - case TWLG.ARABIC_LEBANON: - case TWLG.ARABIC_LIBYA: - case TWLG.ARABIC_MOROCCO: - case TWLG.ARABIC_OMAN: - case TWLG.ARABIC_QATAR: - case TWLG.ARABIC_SAUDIARABIA: - case TWLG.ARABIC_SYRIA: - case TWLG.ARABIC_TUNISIA: - case TWLG.ARABIC_UAE: - case TWLG.ARABIC_YEMEN: - case TWLG.FARSI: - case TWLG.URDU: - m_encoding = Encoding.GetEncoding(1256); - break; - - case TWLG.ESTONIAN: - case TWLG.LATVIAN: - case TWLG.LITHUANIAN: - m_encoding = Encoding.GetEncoding(1257); - break; - - case TWLG.VIETNAMESE: - m_encoding = Encoding.GetEncoding(1258); - break; - - case TWLG.ASSAMESE: - case TWLG.BENGALI: - case TWLG.BIHARI: - case TWLG.BODO: - case TWLG.DOGRI: - case TWLG.GUJARATI: - case TWLG.HARYANVI: - case TWLG.HINDI: - case TWLG.KANNADA: - case TWLG.KASHMIRI: - case TWLG.MALAYALAM: - case TWLG.MARATHI: - case TWLG.MARWARI: - case TWLG.MEGHALAYAN: - case TWLG.MIZO: - case TWLG.NAGA: - case TWLG.ORISSI: - case TWLG.PUNJABI: - case TWLG.PUSHTU: - case TWLG.SIKKIMI: - case TWLG.TAMIL: - case TWLG.TELUGU: - case TWLG.TRIPURI: - // NOTE: there are no known code pages for these, so we will use English - m_encoding = Encoding.GetEncoding(1252); - break; - } - } - - private static Encoding m_encoding = Encoding.GetEncoding(1252); - } - - #endregion - } + +/// +/// Used for strings that go up to 64-bytes... +/// +[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)] +public partial struct TW_STR64 +{ + /// + /// We're stuck with this, because marshalling with packed alignment + /// can't handle arrays... + /// + private byte byItem000; private byte byItem001; private byte byItem002; private byte byItem003; + private byte byItem004; private byte byItem005; private byte byItem006; private byte byItem007; + private byte byItem008; private byte byItem009; private byte byItem010; private byte byItem011; + private byte byItem012; private byte byItem013; private byte byItem014; private byte byItem015; + private byte byItem016; private byte byItem017; private byte byItem018; private byte byItem019; + private byte byItem020; private byte byItem021; private byte byItem022; private byte byItem023; + private byte byItem024; private byte byItem025; private byte byItem026; private byte byItem027; + private byte byItem028; private byte byItem029; private byte byItem030; private byte byItem031; + private byte byItem032; private byte byItem033; private byte byItem034; private byte byItem035; + private byte byItem036; private byte byItem037; private byte byItem038; private byte byItem039; + private byte byItem040; private byte byItem041; private byte byItem042; private byte byItem043; + private byte byItem044; private byte byItem045; private byte byItem046; private byte byItem047; + private byte byItem048; private byte byItem049; private byte byItem050; private byte byItem051; + private byte byItem052; private byte byItem053; private byte byItem054; private byte byItem055; + private byte byItem056; private byte byItem057; private byte byItem058; private byte byItem059; + private byte byItem060; private byte byItem061; private byte byItem062; private byte byItem063; + private byte byItem064; private byte byItem065; + + /// + /// The normal get... + /// + /// + /// + public string Get(Encoding? encoding = null) + { + return (GetValue(true, encoding)); + } + + /// + /// Use this on Mac OS X if you have a call that uses a string + /// that doesn't include the prefix byte... + /// + /// + /// + public string GetNoPrefix(Encoding? encoding = null) + { + return (GetValue(false, encoding)); + } + + /// + /// Get our value... + /// + /// + /// + /// + private string GetValue(bool a_blMayHavePrefix, Encoding? encoding = null) + { + // convert what we have into a byte array + byte[] abyItem = new byte[66]; + abyItem[0] = byItem000; abyItem[1] = byItem001; abyItem[2] = byItem002; abyItem[3] = byItem003; + abyItem[4] = byItem004; abyItem[5] = byItem005; abyItem[6] = byItem006; abyItem[7] = byItem007; + abyItem[8] = byItem008; abyItem[9] = byItem009; abyItem[10] = byItem010; abyItem[11] = byItem011; + abyItem[12] = byItem012; abyItem[13] = byItem013; abyItem[14] = byItem014; abyItem[15] = byItem015; + abyItem[16] = byItem016; abyItem[17] = byItem017; abyItem[18] = byItem018; abyItem[19] = byItem019; + abyItem[20] = byItem020; abyItem[21] = byItem021; abyItem[22] = byItem022; abyItem[23] = byItem023; + abyItem[24] = byItem024; abyItem[25] = byItem025; abyItem[26] = byItem026; abyItem[27] = byItem027; + abyItem[28] = byItem028; abyItem[29] = byItem029; abyItem[30] = byItem030; abyItem[31] = byItem031; + abyItem[32] = byItem032; abyItem[33] = byItem033; abyItem[34] = byItem034; abyItem[35] = byItem035; + abyItem[36] = byItem036; abyItem[37] = byItem037; abyItem[38] = byItem038; abyItem[39] = byItem039; + abyItem[40] = byItem040; abyItem[41] = byItem041; abyItem[42] = byItem042; abyItem[43] = byItem043; + abyItem[44] = byItem044; abyItem[45] = byItem045; abyItem[46] = byItem046; abyItem[47] = byItem047; + abyItem[48] = byItem048; abyItem[49] = byItem049; abyItem[50] = byItem050; abyItem[51] = byItem051; + abyItem[52] = byItem052; abyItem[53] = byItem053; abyItem[54] = byItem054; abyItem[55] = byItem055; + abyItem[56] = byItem056; abyItem[57] = byItem057; abyItem[58] = byItem058; abyItem[59] = byItem059; + abyItem[60] = byItem060; abyItem[61] = byItem061; abyItem[62] = byItem062; abyItem[63] = byItem063; + abyItem[64] = byItem064; abyItem[65] = byItem065; + + // Zero anything after the NUL... + bool blNul = false; + for (int ii = 0; ii < abyItem.Length; ii++) + { + if (!blNul && (abyItem[ii] == 0)) + { + blNul = true; + } + else if (blNul) + { + abyItem[ii] = 0; + } + } + + // change encoding of byte array, then convert the bytes array to a string + string sz = Encoding.Unicode.GetString(Encoding.Convert(encoding ?? Language.GetEncoding(), Encoding.Unicode, abyItem)); + + // If the first character is a NUL, then return the empty string... + if (sz[0] == '\0') + { + return (""); + } + + // If we're running on a Mac, take off the prefix 'byte'... + if (a_blMayHavePrefix && TWPlatform.IsMacOSX) + { + sz = sz.Remove(0, 1); + } + + // If we detect a NUL, then split around it... + if (sz.IndexOf('\0') >= 0) + { + sz = sz.Split(new char[] { '\0' })[0]; + } + + // All done... + return (sz); + } + + /// + /// The normal set... + /// + /// + /// + /// + public void Set(string a_sz, Encoding? encoding = null) + { + SetValue(a_sz, true, encoding); + } + + /// + /// Use this on Mac OS X if you have a call that uses a string + /// that doesn't include the prefix byte... + /// + /// + /// + /// + public void SetNoPrefix(string a_sz, Encoding? encoding = null) + { + SetValue(a_sz, false, encoding); + } + + /// + /// Set our value... + /// + /// + /// + /// + private void SetValue(string a_sz, bool a_blMayHavePrefix, Encoding? encoding = null) + { + // If we're running on a Mac, tack on the prefix 'byte'... + if (a_sz == null) + { + a_sz = ""; + } + else if (a_blMayHavePrefix && TWPlatform.IsMacOSX) + { + a_sz = (char)a_sz.Length + a_sz; + } + + // Make sure that we're NUL padded... + string sz = + a_sz + + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + + "\0\0"; + if (sz.Length > 66) + { + sz = sz.Remove(66); + } + + // convert string to byte array, then change the encoding of the byte array + byte[] abyItem = Encoding.Convert(Encoding.Unicode, encoding ?? Language.GetEncoding(), Encoding.Unicode.GetBytes(sz)); + + // concert byte array to bytes + byItem000 = abyItem[0]; byItem001 = abyItem[1]; byItem002 = abyItem[2]; byItem003 = abyItem[3]; + byItem004 = abyItem[4]; byItem005 = abyItem[5]; byItem006 = abyItem[6]; byItem007 = abyItem[7]; + byItem008 = abyItem[8]; byItem009 = abyItem[9]; byItem010 = abyItem[10]; byItem011 = abyItem[11]; + byItem012 = abyItem[12]; byItem013 = abyItem[13]; byItem014 = abyItem[14]; byItem015 = abyItem[15]; + byItem016 = abyItem[16]; byItem017 = abyItem[17]; byItem018 = abyItem[18]; byItem019 = abyItem[19]; + byItem020 = abyItem[20]; byItem021 = abyItem[21]; byItem022 = abyItem[22]; byItem023 = abyItem[23]; + byItem024 = abyItem[24]; byItem025 = abyItem[25]; byItem026 = abyItem[26]; byItem027 = abyItem[27]; + byItem028 = abyItem[28]; byItem029 = abyItem[29]; byItem030 = abyItem[30]; byItem031 = abyItem[31]; + byItem032 = abyItem[32]; byItem033 = abyItem[33]; byItem034 = abyItem[34]; byItem035 = abyItem[35]; + byItem036 = abyItem[36]; byItem037 = abyItem[37]; byItem038 = abyItem[38]; byItem039 = abyItem[39]; + byItem040 = abyItem[40]; byItem041 = abyItem[41]; byItem042 = abyItem[42]; byItem043 = abyItem[43]; + byItem044 = abyItem[44]; byItem045 = abyItem[45]; byItem046 = abyItem[46]; byItem047 = abyItem[47]; + byItem048 = abyItem[48]; byItem049 = abyItem[49]; byItem050 = abyItem[50]; byItem051 = abyItem[51]; + byItem052 = abyItem[52]; byItem053 = abyItem[53]; byItem054 = abyItem[54]; byItem055 = abyItem[55]; + byItem056 = abyItem[56]; byItem057 = abyItem[57]; byItem058 = abyItem[58]; byItem059 = abyItem[59]; + byItem060 = abyItem[60]; byItem061 = abyItem[61]; byItem062 = abyItem[62]; byItem063 = abyItem[63]; + byItem064 = abyItem[64]; byItem065 = abyItem[65]; + } +} + +/// +/// Used for strings that go up to 128-bytes... +/// +[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)] +public partial struct TW_STR128 +{ + /// + /// We're stuck with this, because marshalling with packed alignment + /// can't handle arrays... + /// + private byte byItem000; private byte byItem001; private byte byItem002; private byte byItem003; + private byte byItem004; private byte byItem005; private byte byItem006; private byte byItem007; + private byte byItem008; private byte byItem009; private byte byItem010; private byte byItem011; + private byte byItem012; private byte byItem013; private byte byItem014; private byte byItem015; + private byte byItem016; private byte byItem017; private byte byItem018; private byte byItem019; + private byte byItem020; private byte byItem021; private byte byItem022; private byte byItem023; + private byte byItem024; private byte byItem025; private byte byItem026; private byte byItem027; + private byte byItem028; private byte byItem029; private byte byItem030; private byte byItem031; + private byte byItem032; private byte byItem033; private byte byItem034; private byte byItem035; + private byte byItem036; private byte byItem037; private byte byItem038; private byte byItem039; + private byte byItem040; private byte byItem041; private byte byItem042; private byte byItem043; + private byte byItem044; private byte byItem045; private byte byItem046; private byte byItem047; + private byte byItem048; private byte byItem049; private byte byItem050; private byte byItem051; + private byte byItem052; private byte byItem053; private byte byItem054; private byte byItem055; + private byte byItem056; private byte byItem057; private byte byItem058; private byte byItem059; + private byte byItem060; private byte byItem061; private byte byItem062; private byte byItem063; + private byte byItem064; private byte byItem065; private byte byItem066; private byte byItem067; + private byte byItem068; private byte byItem069; private byte byItem070; private byte byItem071; + private byte byItem072; private byte byItem073; private byte byItem074; private byte byItem075; + private byte byItem076; private byte byItem077; private byte byItem078; private byte byItem079; + private byte byItem080; private byte byItem081; private byte byItem082; private byte byItem083; + private byte byItem084; private byte byItem085; private byte byItem086; private byte byItem087; + private byte byItem088; private byte byItem089; private byte byItem090; private byte byItem091; + private byte byItem092; private byte byItem093; private byte byItem094; private byte byItem095; + private byte byItem096; private byte byItem097; private byte byItem098; private byte byItem099; + private byte byItem100; private byte byItem101; private byte byItem102; private byte byItem103; + private byte byItem104; private byte byItem105; private byte byItem106; private byte byItem107; + private byte byItem108; private byte byItem109; private byte byItem110; private byte byItem111; + private byte byItem112; private byte byItem113; private byte byItem114; private byte byItem115; + private byte byItem116; private byte byItem117; private byte byItem118; private byte byItem119; + private byte byItem120; private byte byItem121; private byte byItem122; private byte byItem123; + private byte byItem124; private byte byItem125; private byte byItem126; private byte byItem127; + private byte byItem128; private byte byItem129; + + /// + /// The normal get... + /// + /// + /// + public string Get(Encoding? encoding = null) + { + return (GetValue(true, encoding)); + } + + /// + /// Use this on Mac OS X if you have a call that uses a string + /// that doesn't include the prefix byte... + /// + /// + /// + public string GetNoPrefix(Encoding? encoding = null) + { + return (GetValue(false, encoding)); + } + + /// + /// Get our value... + /// + /// + /// + /// + private string GetValue(bool a_blMayHavePrefix, Encoding? encoding = null) + { + // convert what we have into a byte array + byte[] abyItem = new byte[130]; + abyItem[0] = byItem000; abyItem[1] = byItem001; abyItem[2] = byItem002; abyItem[3] = byItem003; + abyItem[4] = byItem004; abyItem[5] = byItem005; abyItem[6] = byItem006; abyItem[7] = byItem007; + abyItem[8] = byItem008; abyItem[9] = byItem009; abyItem[10] = byItem010; abyItem[11] = byItem011; + abyItem[12] = byItem012; abyItem[13] = byItem013; abyItem[14] = byItem014; abyItem[15] = byItem015; + abyItem[16] = byItem016; abyItem[17] = byItem017; abyItem[18] = byItem018; abyItem[19] = byItem019; + abyItem[20] = byItem020; abyItem[21] = byItem021; abyItem[22] = byItem022; abyItem[23] = byItem023; + abyItem[24] = byItem024; abyItem[25] = byItem025; abyItem[26] = byItem026; abyItem[27] = byItem027; + abyItem[28] = byItem028; abyItem[29] = byItem029; abyItem[30] = byItem030; abyItem[31] = byItem031; + abyItem[32] = byItem032; abyItem[33] = byItem033; abyItem[34] = byItem034; abyItem[35] = byItem035; + abyItem[36] = byItem036; abyItem[37] = byItem037; abyItem[38] = byItem038; abyItem[39] = byItem039; + abyItem[40] = byItem040; abyItem[41] = byItem041; abyItem[42] = byItem042; abyItem[43] = byItem043; + abyItem[44] = byItem044; abyItem[45] = byItem045; abyItem[46] = byItem046; abyItem[47] = byItem047; + abyItem[48] = byItem048; abyItem[49] = byItem049; abyItem[50] = byItem050; abyItem[51] = byItem051; + abyItem[52] = byItem052; abyItem[53] = byItem053; abyItem[54] = byItem054; abyItem[55] = byItem055; + abyItem[56] = byItem056; abyItem[57] = byItem057; abyItem[58] = byItem058; abyItem[59] = byItem059; + abyItem[60] = byItem060; abyItem[61] = byItem061; abyItem[62] = byItem062; abyItem[63] = byItem063; + abyItem[64] = byItem064; abyItem[65] = byItem065; abyItem[66] = byItem066; abyItem[67] = byItem067; + abyItem[68] = byItem068; abyItem[69] = byItem069; abyItem[70] = byItem070; abyItem[71] = byItem071; + abyItem[72] = byItem072; abyItem[73] = byItem073; abyItem[74] = byItem074; abyItem[75] = byItem075; + abyItem[76] = byItem076; abyItem[77] = byItem077; abyItem[78] = byItem078; abyItem[79] = byItem079; + abyItem[80] = byItem080; abyItem[81] = byItem081; abyItem[82] = byItem082; abyItem[83] = byItem083; + abyItem[84] = byItem084; abyItem[85] = byItem085; abyItem[86] = byItem086; abyItem[87] = byItem087; + abyItem[88] = byItem088; abyItem[89] = byItem089; abyItem[90] = byItem090; abyItem[91] = byItem091; + abyItem[92] = byItem092; abyItem[93] = byItem093; abyItem[94] = byItem094; abyItem[95] = byItem095; + abyItem[96] = byItem096; abyItem[97] = byItem097; abyItem[98] = byItem098; abyItem[99] = byItem099; + abyItem[100] = byItem100; abyItem[101] = byItem101; abyItem[102] = byItem102; abyItem[103] = byItem103; + abyItem[104] = byItem104; abyItem[105] = byItem105; abyItem[106] = byItem106; abyItem[107] = byItem107; + abyItem[108] = byItem108; abyItem[109] = byItem109; abyItem[110] = byItem110; abyItem[111] = byItem111; + abyItem[112] = byItem112; abyItem[113] = byItem113; abyItem[114] = byItem114; abyItem[115] = byItem115; + abyItem[116] = byItem116; abyItem[117] = byItem117; abyItem[118] = byItem118; abyItem[119] = byItem119; + abyItem[120] = byItem120; abyItem[121] = byItem121; abyItem[122] = byItem122; abyItem[123] = byItem123; + abyItem[124] = byItem124; abyItem[125] = byItem125; abyItem[126] = byItem126; abyItem[127] = byItem127; + abyItem[128] = byItem128; abyItem[129] = byItem129; + + // Zero anything after the NUL... + bool blNul = false; + for (int ii = 0; ii < abyItem.Length; ii++) + { + if (!blNul && (abyItem[ii] == 0)) + { + blNul = true; + } + else if (blNul) + { + abyItem[ii] = 0; + } + } + + // change encoding of byte array, then convert the bytes array to a string + string sz = Encoding.Unicode.GetString(Encoding.Convert(encoding ?? Language.GetEncoding(), Encoding.Unicode, abyItem)); + + // If the first character is a NUL, then return the empty string... + if (sz[0] == '\0') + { + return (""); + } + + // If we're running on a Mac, take off the prefix 'byte'... + if (a_blMayHavePrefix && TWPlatform.IsMacOSX) + { + sz = sz.Remove(0, 1); + } + + // If we detect a NUL, then split around it... + if (sz.IndexOf('\0') >= 0) + { + sz = sz.Split(new char[] { '\0' })[0]; + } + + // All done... + return (sz); + } + + /// + /// The normal set... + /// + /// + /// + /// + public void Set(string a_sz, Encoding? encoding = null) + { + SetValue(a_sz, true, encoding); + } + + /// + /// Use this on Mac OS X if you have a call that uses a string + /// that doesn't include the prefix byte... + /// + /// + /// + /// + public void SetNoPrefix(string a_sz, Encoding? encoding = null) + { + SetValue(a_sz, false, encoding); + } + + /// + /// Set our value... + /// + /// + /// + /// + private void SetValue(string a_sz, bool a_blMayHavePrefix, Encoding? encoding = null) + { + // If we're running on a Mac, tack on the prefix 'byte'... + if (a_sz == null) + { + a_sz = ""; + } + else if (a_blMayHavePrefix && TWPlatform.IsMacOSX) + { + a_sz = (char)a_sz.Length + a_sz; + } + + // Make sure that we're NUL padded... + string sz = + a_sz + + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + + "\0\0"; + if (sz.Length > 130) + { + sz = sz.Remove(130); + } + + // convert string to byte array, then change the encoding of the byte array + byte[] abyItem = Encoding.Convert(Encoding.Unicode, encoding ?? Language.GetEncoding(), Encoding.Unicode.GetBytes(sz)); + + // concert byte array to bytes + byItem000 = abyItem[0]; byItem001 = abyItem[1]; byItem002 = abyItem[2]; byItem003 = abyItem[3]; + byItem004 = abyItem[4]; byItem005 = abyItem[5]; byItem006 = abyItem[6]; byItem007 = abyItem[7]; + byItem008 = abyItem[8]; byItem009 = abyItem[9]; byItem010 = abyItem[10]; byItem011 = abyItem[11]; + byItem012 = abyItem[12]; byItem013 = abyItem[13]; byItem014 = abyItem[14]; byItem015 = abyItem[15]; + byItem016 = abyItem[16]; byItem017 = abyItem[17]; byItem018 = abyItem[18]; byItem019 = abyItem[19]; + byItem020 = abyItem[20]; byItem021 = abyItem[21]; byItem022 = abyItem[22]; byItem023 = abyItem[23]; + byItem024 = abyItem[24]; byItem025 = abyItem[25]; byItem026 = abyItem[26]; byItem027 = abyItem[27]; + byItem028 = abyItem[28]; byItem029 = abyItem[29]; byItem030 = abyItem[30]; byItem031 = abyItem[31]; + byItem032 = abyItem[32]; byItem033 = abyItem[33]; byItem034 = abyItem[34]; byItem035 = abyItem[35]; + byItem036 = abyItem[36]; byItem037 = abyItem[37]; byItem038 = abyItem[38]; byItem039 = abyItem[39]; + byItem040 = abyItem[40]; byItem041 = abyItem[41]; byItem042 = abyItem[42]; byItem043 = abyItem[43]; + byItem044 = abyItem[44]; byItem045 = abyItem[45]; byItem046 = abyItem[46]; byItem047 = abyItem[47]; + byItem048 = abyItem[48]; byItem049 = abyItem[49]; byItem050 = abyItem[50]; byItem051 = abyItem[51]; + byItem052 = abyItem[52]; byItem053 = abyItem[53]; byItem054 = abyItem[54]; byItem055 = abyItem[55]; + byItem056 = abyItem[56]; byItem057 = abyItem[57]; byItem058 = abyItem[58]; byItem059 = abyItem[59]; + byItem060 = abyItem[60]; byItem061 = abyItem[61]; byItem062 = abyItem[62]; byItem063 = abyItem[63]; + byItem064 = abyItem[64]; byItem065 = abyItem[65]; byItem066 = abyItem[66]; byItem067 = abyItem[67]; + byItem068 = abyItem[68]; byItem069 = abyItem[69]; byItem070 = abyItem[70]; byItem071 = abyItem[71]; + byItem072 = abyItem[72]; byItem073 = abyItem[73]; byItem074 = abyItem[74]; byItem075 = abyItem[75]; + byItem076 = abyItem[76]; byItem077 = abyItem[77]; byItem078 = abyItem[78]; byItem079 = abyItem[79]; + byItem080 = abyItem[80]; byItem081 = abyItem[81]; byItem082 = abyItem[82]; byItem083 = abyItem[83]; + byItem084 = abyItem[84]; byItem085 = abyItem[85]; byItem086 = abyItem[86]; byItem087 = abyItem[87]; + byItem088 = abyItem[88]; byItem089 = abyItem[89]; byItem090 = abyItem[90]; byItem091 = abyItem[91]; + byItem092 = abyItem[92]; byItem093 = abyItem[93]; byItem094 = abyItem[94]; byItem095 = abyItem[95]; + byItem096 = abyItem[96]; byItem097 = abyItem[97]; byItem098 = abyItem[98]; byItem099 = abyItem[99]; + byItem100 = abyItem[100]; byItem101 = abyItem[101]; byItem102 = abyItem[102]; byItem103 = abyItem[103]; + byItem104 = abyItem[104]; byItem105 = abyItem[105]; byItem106 = abyItem[106]; byItem107 = abyItem[107]; + byItem108 = abyItem[108]; byItem109 = abyItem[109]; byItem110 = abyItem[110]; byItem111 = abyItem[111]; + byItem112 = abyItem[112]; byItem113 = abyItem[113]; byItem114 = abyItem[114]; byItem115 = abyItem[115]; + byItem116 = abyItem[116]; byItem117 = abyItem[117]; byItem118 = abyItem[118]; byItem119 = abyItem[119]; + byItem120 = abyItem[120]; byItem121 = abyItem[121]; byItem122 = abyItem[122]; byItem123 = abyItem[123]; + byItem124 = abyItem[124]; byItem125 = abyItem[125]; byItem126 = abyItem[126]; byItem127 = abyItem[127]; + byItem128 = abyItem[128]; byItem129 = abyItem[129]; + } +} + +/// +/// Used for strings that go up to 256-bytes... +/// +[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)] +public partial struct TW_STR255 +{ + /// + /// We're stuck with this, because marshalling with packed alignment + /// can't handle arrays... + /// + private byte byItem000; private byte byItem001; private byte byItem002; private byte byItem003; + private byte byItem004; private byte byItem005; private byte byItem006; private byte byItem007; + private byte byItem008; private byte byItem009; private byte byItem010; private byte byItem011; + private byte byItem012; private byte byItem013; private byte byItem014; private byte byItem015; + private byte byItem016; private byte byItem017; private byte byItem018; private byte byItem019; + private byte byItem020; private byte byItem021; private byte byItem022; private byte byItem023; + private byte byItem024; private byte byItem025; private byte byItem026; private byte byItem027; + private byte byItem028; private byte byItem029; private byte byItem030; private byte byItem031; + private byte byItem032; private byte byItem033; private byte byItem034; private byte byItem035; + private byte byItem036; private byte byItem037; private byte byItem038; private byte byItem039; + private byte byItem040; private byte byItem041; private byte byItem042; private byte byItem043; + private byte byItem044; private byte byItem045; private byte byItem046; private byte byItem047; + private byte byItem048; private byte byItem049; private byte byItem050; private byte byItem051; + private byte byItem052; private byte byItem053; private byte byItem054; private byte byItem055; + private byte byItem056; private byte byItem057; private byte byItem058; private byte byItem059; + private byte byItem060; private byte byItem061; private byte byItem062; private byte byItem063; + private byte byItem064; private byte byItem065; private byte byItem066; private byte byItem067; + private byte byItem068; private byte byItem069; private byte byItem070; private byte byItem071; + private byte byItem072; private byte byItem073; private byte byItem074; private byte byItem075; + private byte byItem076; private byte byItem077; private byte byItem078; private byte byItem079; + private byte byItem080; private byte byItem081; private byte byItem082; private byte byItem083; + private byte byItem084; private byte byItem085; private byte byItem086; private byte byItem087; + private byte byItem088; private byte byItem089; private byte byItem090; private byte byItem091; + private byte byItem092; private byte byItem093; private byte byItem094; private byte byItem095; + private byte byItem096; private byte byItem097; private byte byItem098; private byte byItem099; + private byte byItem100; private byte byItem101; private byte byItem102; private byte byItem103; + private byte byItem104; private byte byItem105; private byte byItem106; private byte byItem107; + private byte byItem108; private byte byItem109; private byte byItem110; private byte byItem111; + private byte byItem112; private byte byItem113; private byte byItem114; private byte byItem115; + private byte byItem116; private byte byItem117; private byte byItem118; private byte byItem119; + private byte byItem120; private byte byItem121; private byte byItem122; private byte byItem123; + private byte byItem124; private byte byItem125; private byte byItem126; private byte byItem127; + private byte byItem128; private byte byItem129; private byte byItem130; private byte byItem131; + private byte byItem132; private byte byItem133; private byte byItem134; private byte byItem135; + private byte byItem136; private byte byItem137; private byte byItem138; private byte byItem139; + private byte byItem140; private byte byItem141; private byte byItem142; private byte byItem143; + private byte byItem144; private byte byItem145; private byte byItem146; private byte byItem147; + private byte byItem148; private byte byItem149; private byte byItem150; private byte byItem151; + private byte byItem152; private byte byItem153; private byte byItem154; private byte byItem155; + private byte byItem156; private byte byItem157; private byte byItem158; private byte byItem159; + private byte byItem160; private byte byItem161; private byte byItem162; private byte byItem163; + private byte byItem164; private byte byItem165; private byte byItem166; private byte byItem167; + private byte byItem168; private byte byItem169; private byte byItem170; private byte byItem171; + private byte byItem172; private byte byItem173; private byte byItem174; private byte byItem175; + private byte byItem176; private byte byItem177; private byte byItem178; private byte byItem179; + private byte byItem180; private byte byItem181; private byte byItem182; private byte byItem183; + private byte byItem184; private byte byItem185; private byte byItem186; private byte byItem187; + private byte byItem188; private byte byItem189; private byte byItem190; private byte byItem191; + private byte byItem192; private byte byItem193; private byte byItem194; private byte byItem195; + private byte byItem196; private byte byItem197; private byte byItem198; private byte byItem199; + private byte byItem200; private byte byItem201; private byte byItem202; private byte byItem203; + private byte byItem204; private byte byItem205; private byte byItem206; private byte byItem207; + private byte byItem208; private byte byItem209; private byte byItem210; private byte byItem211; + private byte byItem212; private byte byItem213; private byte byItem214; private byte byItem215; + private byte byItem216; private byte byItem217; private byte byItem218; private byte byItem219; + private byte byItem220; private byte byItem221; private byte byItem222; private byte byItem223; + private byte byItem224; private byte byItem225; private byte byItem226; private byte byItem227; + private byte byItem228; private byte byItem229; private byte byItem230; private byte byItem231; + private byte byItem232; private byte byItem233; private byte byItem234; private byte byItem235; + private byte byItem236; private byte byItem237; private byte byItem238; private byte byItem239; + private byte byItem240; private byte byItem241; private byte byItem242; private byte byItem243; + private byte byItem244; private byte byItem245; private byte byItem246; private byte byItem247; + private byte byItem248; private byte byItem249; private byte byItem250; private byte byItem251; + private byte byItem252; private byte byItem253; private byte byItem254; private byte byItem255; + + /// + /// The normal get... + /// + /// + /// + public string Get(Encoding? encoding = null) + { + return (GetValue(true, encoding)); + } + + /// + /// Use this on Mac OS X if you have a call that uses a string + /// that doesn't include the prefix byte... + /// + /// + /// + public string GetNoPrefix(Encoding? encoding = null) + { + return (GetValue(false, encoding)); + } + + /// + /// Get our value... + /// + /// + /// + /// + private string GetValue(bool a_blMayHavePrefix, Encoding? encoding = null) + { + // convert what we have into a byte array + byte[] abyItem = new byte[256]; + abyItem[0] = byItem000; abyItem[1] = byItem001; abyItem[2] = byItem002; abyItem[3] = byItem003; + abyItem[4] = byItem004; abyItem[5] = byItem005; abyItem[6] = byItem006; abyItem[7] = byItem007; + abyItem[8] = byItem008; abyItem[9] = byItem009; abyItem[10] = byItem010; abyItem[11] = byItem011; + abyItem[12] = byItem012; abyItem[13] = byItem013; abyItem[14] = byItem014; abyItem[15] = byItem015; + abyItem[16] = byItem016; abyItem[17] = byItem017; abyItem[18] = byItem018; abyItem[19] = byItem019; + abyItem[20] = byItem020; abyItem[21] = byItem021; abyItem[22] = byItem022; abyItem[23] = byItem023; + abyItem[24] = byItem024; abyItem[25] = byItem025; abyItem[26] = byItem026; abyItem[27] = byItem027; + abyItem[28] = byItem028; abyItem[29] = byItem029; abyItem[30] = byItem030; abyItem[31] = byItem031; + abyItem[32] = byItem032; abyItem[33] = byItem033; abyItem[34] = byItem034; abyItem[35] = byItem035; + abyItem[36] = byItem036; abyItem[37] = byItem037; abyItem[38] = byItem038; abyItem[39] = byItem039; + abyItem[40] = byItem040; abyItem[41] = byItem041; abyItem[42] = byItem042; abyItem[43] = byItem043; + abyItem[44] = byItem044; abyItem[45] = byItem045; abyItem[46] = byItem046; abyItem[47] = byItem047; + abyItem[48] = byItem048; abyItem[49] = byItem049; abyItem[50] = byItem050; abyItem[51] = byItem051; + abyItem[52] = byItem052; abyItem[53] = byItem053; abyItem[54] = byItem054; abyItem[55] = byItem055; + abyItem[56] = byItem056; abyItem[57] = byItem057; abyItem[58] = byItem058; abyItem[59] = byItem059; + abyItem[60] = byItem060; abyItem[61] = byItem061; abyItem[62] = byItem062; abyItem[63] = byItem063; + abyItem[64] = byItem064; abyItem[65] = byItem065; abyItem[66] = byItem066; abyItem[67] = byItem067; + abyItem[68] = byItem068; abyItem[69] = byItem069; abyItem[70] = byItem070; abyItem[71] = byItem071; + abyItem[72] = byItem072; abyItem[73] = byItem073; abyItem[74] = byItem074; abyItem[75] = byItem075; + abyItem[76] = byItem076; abyItem[77] = byItem077; abyItem[78] = byItem078; abyItem[79] = byItem079; + abyItem[80] = byItem080; abyItem[81] = byItem081; abyItem[82] = byItem082; abyItem[83] = byItem083; + abyItem[84] = byItem084; abyItem[85] = byItem085; abyItem[86] = byItem086; abyItem[87] = byItem087; + abyItem[88] = byItem088; abyItem[89] = byItem089; abyItem[90] = byItem090; abyItem[91] = byItem091; + abyItem[92] = byItem092; abyItem[93] = byItem093; abyItem[94] = byItem094; abyItem[95] = byItem095; + abyItem[96] = byItem096; abyItem[97] = byItem097; abyItem[98] = byItem098; abyItem[99] = byItem099; + abyItem[100] = byItem100; abyItem[101] = byItem101; abyItem[102] = byItem102; abyItem[103] = byItem103; + abyItem[104] = byItem104; abyItem[105] = byItem105; abyItem[106] = byItem106; abyItem[107] = byItem107; + abyItem[108] = byItem108; abyItem[109] = byItem109; abyItem[110] = byItem110; abyItem[111] = byItem111; + abyItem[112] = byItem112; abyItem[113] = byItem113; abyItem[114] = byItem114; abyItem[115] = byItem115; + abyItem[116] = byItem116; abyItem[117] = byItem117; abyItem[118] = byItem118; abyItem[119] = byItem119; + abyItem[120] = byItem120; abyItem[121] = byItem121; abyItem[122] = byItem122; abyItem[123] = byItem123; + abyItem[124] = byItem124; abyItem[125] = byItem125; abyItem[126] = byItem126; abyItem[127] = byItem127; + abyItem[128] = byItem128; abyItem[129] = byItem129; abyItem[130] = byItem130; abyItem[131] = byItem131; + abyItem[132] = byItem132; abyItem[133] = byItem133; abyItem[134] = byItem134; abyItem[135] = byItem135; + abyItem[136] = byItem136; abyItem[137] = byItem137; abyItem[138] = byItem138; abyItem[139] = byItem139; + abyItem[140] = byItem140; abyItem[141] = byItem141; abyItem[142] = byItem142; abyItem[143] = byItem143; + abyItem[144] = byItem144; abyItem[145] = byItem145; abyItem[146] = byItem146; abyItem[147] = byItem147; + abyItem[148] = byItem148; abyItem[149] = byItem149; abyItem[150] = byItem150; abyItem[151] = byItem151; + abyItem[152] = byItem152; abyItem[153] = byItem153; abyItem[154] = byItem154; abyItem[155] = byItem155; + abyItem[156] = byItem156; abyItem[157] = byItem157; abyItem[158] = byItem158; abyItem[159] = byItem159; + abyItem[160] = byItem160; abyItem[161] = byItem161; abyItem[162] = byItem162; abyItem[163] = byItem163; + abyItem[164] = byItem164; abyItem[165] = byItem165; abyItem[166] = byItem166; abyItem[167] = byItem167; + abyItem[168] = byItem168; abyItem[169] = byItem169; abyItem[170] = byItem170; abyItem[171] = byItem171; + abyItem[172] = byItem172; abyItem[173] = byItem173; abyItem[174] = byItem174; abyItem[175] = byItem175; + abyItem[176] = byItem176; abyItem[177] = byItem177; abyItem[178] = byItem178; abyItem[179] = byItem179; + abyItem[180] = byItem180; abyItem[181] = byItem181; abyItem[182] = byItem182; abyItem[183] = byItem183; + abyItem[184] = byItem184; abyItem[185] = byItem185; abyItem[186] = byItem186; abyItem[187] = byItem187; + abyItem[188] = byItem188; abyItem[189] = byItem189; abyItem[190] = byItem190; abyItem[191] = byItem191; + abyItem[192] = byItem192; abyItem[193] = byItem193; abyItem[194] = byItem194; abyItem[195] = byItem195; + abyItem[196] = byItem196; abyItem[197] = byItem197; abyItem[198] = byItem198; abyItem[199] = byItem199; + abyItem[200] = byItem200; abyItem[201] = byItem201; abyItem[202] = byItem202; abyItem[203] = byItem203; + abyItem[204] = byItem204; abyItem[205] = byItem205; abyItem[206] = byItem206; abyItem[207] = byItem207; + abyItem[208] = byItem208; abyItem[209] = byItem209; abyItem[210] = byItem210; abyItem[211] = byItem211; + abyItem[212] = byItem212; abyItem[213] = byItem213; abyItem[214] = byItem214; abyItem[215] = byItem215; + abyItem[216] = byItem216; abyItem[217] = byItem217; abyItem[218] = byItem218; abyItem[219] = byItem219; + abyItem[220] = byItem220; abyItem[221] = byItem221; abyItem[222] = byItem222; abyItem[223] = byItem223; + abyItem[224] = byItem224; abyItem[225] = byItem225; abyItem[226] = byItem226; abyItem[227] = byItem227; + abyItem[228] = byItem228; abyItem[229] = byItem229; abyItem[230] = byItem230; abyItem[231] = byItem231; + abyItem[232] = byItem232; abyItem[233] = byItem233; abyItem[234] = byItem234; abyItem[235] = byItem235; + abyItem[236] = byItem236; abyItem[237] = byItem237; abyItem[238] = byItem238; abyItem[239] = byItem239; + abyItem[240] = byItem240; abyItem[241] = byItem241; abyItem[242] = byItem242; abyItem[243] = byItem243; + abyItem[244] = byItem244; abyItem[245] = byItem245; abyItem[246] = byItem246; abyItem[247] = byItem247; + abyItem[248] = byItem248; abyItem[249] = byItem249; abyItem[250] = byItem250; abyItem[251] = byItem251; + abyItem[252] = byItem252; abyItem[253] = byItem253; abyItem[254] = byItem254; abyItem[255] = byItem255; + + // Zero anything after the NUL... + bool blNul = false; + for (int ii = 0; ii < abyItem.Length; ii++) + { + if (!blNul && (abyItem[ii] == 0)) + { + blNul = true; + } + else if (blNul) + { + abyItem[ii] = 0; + } + } + + // change encoding of byte array, then convert the bytes array to a string + string sz = Encoding.Unicode.GetString(Encoding.Convert(encoding ?? Language.GetEncoding(), Encoding.Unicode, abyItem)); + + // If the first character is a NUL, then return the empty string... + if (sz[0] == '\0') + { + return (""); + } + + // If we're running on a Mac, take off the prefix 'byte'... + if (a_blMayHavePrefix && TWPlatform.IsMacOSX) + { + sz = sz.Remove(0, 1); + } + + // If we detect a NUL, then split around it... + if (sz.IndexOf('\0') >= 0) + { + sz = sz.Split(new char[] { '\0' })[0]; + } + + // All done... + return (sz); + } + + /// + /// The normal set... + /// + /// + /// + /// + public void Set(string a_sz, Encoding? encoding = null) + { + SetValue(a_sz, true, encoding); + } + + /// + /// Use this on Mac OS X if you have a call that uses a string + /// that doesn't include the prefix byte... + /// + /// + /// + /// + public void SetNoPrefix(string a_sz, Encoding? encoding = null) + { + SetValue(a_sz, false, encoding); + } + + /// + /// Set our value... + /// + /// + /// + /// + private void SetValue(string a_sz, bool a_blMayHavePrefix, Encoding? encoding = null) + { + // If we're running on a Mac, tack on the prefix 'byte'... + if (a_sz == null) + { + a_sz = ""; + } + else if (a_blMayHavePrefix && TWPlatform.IsMacOSX) + { + a_sz = (char)a_sz.Length + a_sz; + } + + // Make sure that we're NUL padded... + string sz = + a_sz + + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; + if (sz.Length > 256) + { + sz = sz.Remove(256); + } + + // convert string to byte array, then change the encoding of the byte array + byte[] abyItem = Encoding.Convert(Encoding.Unicode, encoding ?? Language.GetEncoding(), Encoding.Unicode.GetBytes(sz)); + + // concert byte array to bytes + byItem000 = abyItem[0]; byItem001 = abyItem[1]; byItem002 = abyItem[2]; byItem003 = abyItem[3]; + byItem004 = abyItem[4]; byItem005 = abyItem[5]; byItem006 = abyItem[6]; byItem007 = abyItem[7]; + byItem008 = abyItem[8]; byItem009 = abyItem[9]; byItem010 = abyItem[10]; byItem011 = abyItem[11]; + byItem012 = abyItem[12]; byItem013 = abyItem[13]; byItem014 = abyItem[14]; byItem015 = abyItem[15]; + byItem016 = abyItem[16]; byItem017 = abyItem[17]; byItem018 = abyItem[18]; byItem019 = abyItem[19]; + byItem020 = abyItem[20]; byItem021 = abyItem[21]; byItem022 = abyItem[22]; byItem023 = abyItem[23]; + byItem024 = abyItem[24]; byItem025 = abyItem[25]; byItem026 = abyItem[26]; byItem027 = abyItem[27]; + byItem028 = abyItem[28]; byItem029 = abyItem[29]; byItem030 = abyItem[30]; byItem031 = abyItem[31]; + byItem032 = abyItem[32]; byItem033 = abyItem[33]; byItem034 = abyItem[34]; byItem035 = abyItem[35]; + byItem036 = abyItem[36]; byItem037 = abyItem[37]; byItem038 = abyItem[38]; byItem039 = abyItem[39]; + byItem040 = abyItem[40]; byItem041 = abyItem[41]; byItem042 = abyItem[42]; byItem043 = abyItem[43]; + byItem044 = abyItem[44]; byItem045 = abyItem[45]; byItem046 = abyItem[46]; byItem047 = abyItem[47]; + byItem048 = abyItem[48]; byItem049 = abyItem[49]; byItem050 = abyItem[50]; byItem051 = abyItem[51]; + byItem052 = abyItem[52]; byItem053 = abyItem[53]; byItem054 = abyItem[54]; byItem055 = abyItem[55]; + byItem056 = abyItem[56]; byItem057 = abyItem[57]; byItem058 = abyItem[58]; byItem059 = abyItem[59]; + byItem060 = abyItem[60]; byItem061 = abyItem[61]; byItem062 = abyItem[62]; byItem063 = abyItem[63]; + byItem064 = abyItem[64]; byItem065 = abyItem[65]; byItem066 = abyItem[66]; byItem067 = abyItem[67]; + byItem068 = abyItem[68]; byItem069 = abyItem[69]; byItem070 = abyItem[70]; byItem071 = abyItem[71]; + byItem072 = abyItem[72]; byItem073 = abyItem[73]; byItem074 = abyItem[74]; byItem075 = abyItem[75]; + byItem076 = abyItem[76]; byItem077 = abyItem[77]; byItem078 = abyItem[78]; byItem079 = abyItem[79]; + byItem080 = abyItem[80]; byItem081 = abyItem[81]; byItem082 = abyItem[82]; byItem083 = abyItem[83]; + byItem084 = abyItem[84]; byItem085 = abyItem[85]; byItem086 = abyItem[86]; byItem087 = abyItem[87]; + byItem088 = abyItem[88]; byItem089 = abyItem[89]; byItem090 = abyItem[90]; byItem091 = abyItem[91]; + byItem092 = abyItem[92]; byItem093 = abyItem[93]; byItem094 = abyItem[94]; byItem095 = abyItem[95]; + byItem096 = abyItem[96]; byItem097 = abyItem[97]; byItem098 = abyItem[98]; byItem099 = abyItem[99]; + byItem100 = abyItem[100]; byItem101 = abyItem[101]; byItem102 = abyItem[102]; byItem103 = abyItem[103]; + byItem104 = abyItem[104]; byItem105 = abyItem[105]; byItem106 = abyItem[106]; byItem107 = abyItem[107]; + byItem108 = abyItem[108]; byItem109 = abyItem[109]; byItem110 = abyItem[110]; byItem111 = abyItem[111]; + byItem112 = abyItem[112]; byItem113 = abyItem[113]; byItem114 = abyItem[114]; byItem115 = abyItem[115]; + byItem116 = abyItem[116]; byItem117 = abyItem[117]; byItem118 = abyItem[118]; byItem119 = abyItem[119]; + byItem120 = abyItem[120]; byItem121 = abyItem[121]; byItem122 = abyItem[122]; byItem123 = abyItem[123]; + byItem124 = abyItem[124]; byItem125 = abyItem[125]; byItem126 = abyItem[126]; byItem127 = abyItem[127]; + byItem128 = abyItem[128]; byItem129 = abyItem[129]; byItem130 = abyItem[130]; byItem131 = abyItem[131]; + byItem132 = abyItem[132]; byItem133 = abyItem[133]; byItem134 = abyItem[134]; byItem135 = abyItem[135]; + byItem136 = abyItem[136]; byItem137 = abyItem[137]; byItem138 = abyItem[138]; byItem139 = abyItem[139]; + byItem140 = abyItem[140]; byItem141 = abyItem[141]; byItem142 = abyItem[142]; byItem143 = abyItem[143]; + byItem144 = abyItem[144]; byItem145 = abyItem[145]; byItem146 = abyItem[146]; byItem147 = abyItem[147]; + byItem148 = abyItem[148]; byItem149 = abyItem[149]; byItem150 = abyItem[150]; byItem151 = abyItem[151]; + byItem152 = abyItem[152]; byItem153 = abyItem[153]; byItem154 = abyItem[154]; byItem155 = abyItem[155]; + byItem156 = abyItem[156]; byItem157 = abyItem[157]; byItem158 = abyItem[158]; byItem159 = abyItem[159]; + byItem160 = abyItem[160]; byItem161 = abyItem[161]; byItem162 = abyItem[162]; byItem163 = abyItem[163]; + byItem164 = abyItem[164]; byItem165 = abyItem[165]; byItem166 = abyItem[166]; byItem167 = abyItem[167]; + byItem168 = abyItem[168]; byItem169 = abyItem[169]; byItem170 = abyItem[170]; byItem171 = abyItem[171]; + byItem172 = abyItem[172]; byItem173 = abyItem[173]; byItem174 = abyItem[174]; byItem175 = abyItem[175]; + byItem176 = abyItem[176]; byItem177 = abyItem[177]; byItem178 = abyItem[178]; byItem179 = abyItem[179]; + byItem180 = abyItem[180]; byItem181 = abyItem[181]; byItem182 = abyItem[182]; byItem183 = abyItem[183]; + byItem184 = abyItem[184]; byItem185 = abyItem[185]; byItem186 = abyItem[186]; byItem187 = abyItem[187]; + byItem188 = abyItem[188]; byItem189 = abyItem[189]; byItem190 = abyItem[190]; byItem191 = abyItem[191]; + byItem192 = abyItem[192]; byItem193 = abyItem[193]; byItem194 = abyItem[194]; byItem195 = abyItem[195]; + byItem196 = abyItem[196]; byItem197 = abyItem[197]; byItem198 = abyItem[198]; byItem199 = abyItem[199]; + byItem200 = abyItem[200]; byItem201 = abyItem[201]; byItem202 = abyItem[202]; byItem203 = abyItem[203]; + byItem204 = abyItem[204]; byItem205 = abyItem[205]; byItem206 = abyItem[206]; byItem207 = abyItem[207]; + byItem208 = abyItem[208]; byItem209 = abyItem[209]; byItem210 = abyItem[210]; byItem211 = abyItem[211]; + byItem212 = abyItem[212]; byItem213 = abyItem[213]; byItem214 = abyItem[214]; byItem215 = abyItem[215]; + byItem216 = abyItem[216]; byItem217 = abyItem[217]; byItem218 = abyItem[218]; byItem219 = abyItem[219]; + byItem220 = abyItem[220]; byItem221 = abyItem[221]; byItem222 = abyItem[222]; byItem223 = abyItem[223]; + byItem224 = abyItem[224]; byItem225 = abyItem[225]; byItem226 = abyItem[226]; byItem227 = abyItem[227]; + byItem228 = abyItem[228]; byItem229 = abyItem[229]; byItem230 = abyItem[230]; byItem231 = abyItem[231]; + byItem232 = abyItem[232]; byItem233 = abyItem[233]; byItem234 = abyItem[234]; byItem235 = abyItem[235]; + byItem236 = abyItem[236]; byItem237 = abyItem[237]; byItem238 = abyItem[238]; byItem239 = abyItem[239]; + byItem240 = abyItem[240]; byItem241 = abyItem[241]; byItem242 = abyItem[242]; byItem243 = abyItem[243]; + byItem244 = abyItem[244]; byItem245 = abyItem[245]; byItem246 = abyItem[246]; byItem247 = abyItem[247]; + byItem248 = abyItem[248]; byItem249 = abyItem[249]; byItem250 = abyItem[250]; byItem251 = abyItem[251]; + byItem252 = abyItem[252]; byItem253 = abyItem[253]; byItem254 = abyItem[254]; byItem255 = abyItem[255]; + } +} + +#endregion + + +/////////////////////////////////////////////////////////////////////////////// +// Structure Definitions... +/////////////////////////////////////////////////////////////////////////////// +#region Structure Definitions.. + +/// +/// Fixed point structure type. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public partial struct TW_FIX32 +{ + public short Whole; + public ushort Frac; +} + +/// +/// Defines a frame rectangle in ICAP_UNITS coordinates. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public partial struct TW_FRAME +{ + public TW_FIX32 Left; + public TW_FIX32 Top; + public TW_FIX32 Right; + public TW_FIX32 Bottom; +} + +/// +/// Defines the parameters used for channel-specific transformation. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_DECODEFUNCTION +{ + public TW_FIX32 StartIn; + public TW_FIX32 BreakIn; + public TW_FIX32 EndIn; + public TW_FIX32 StartOut; + public TW_FIX32 BreakOut; + public TW_FIX32 EndOut; + public TW_FIX32 Gamma; + public TW_FIX32 SampleCount; +} + +/// +/// Stores a Fixed point number in two parts, a whole and a fractional part. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_TRANSFORMSTAGE +{ + public TW_DECODEFUNCTION Decode_0; + public TW_DECODEFUNCTION Decode_1; + public TW_DECODEFUNCTION Decode_2; + public TW_FIX32 Mix_0_0; + public TW_FIX32 Mix_0_1; + public TW_FIX32 Mix_0_2; + public TW_FIX32 Mix_1_0; + public TW_FIX32 Mix_1_1; + public TW_FIX32 Mix_1_2; + public TW_FIX32 Mix_2_0; + public TW_FIX32 Mix_2_1; + public TW_FIX32 Mix_2_2; +} + +/// +/// Stores a list of values for a capability, the ItemList is commented +/// out so that the caller can collect information about it with a +/// marshalling call... +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_ARRAY +{ + public TWTY ItemType; + public uint NumItems; + //public byte[] ItemList; +} +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_ARRAY_MACOSX +{ + public uint ItemType; + public uint NumItems; + //public byte[] ItemList; +} + +/// +/// Information about audio data. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_AUDIOINFO +{ + public TW_STR255 Name; + public uint Reserved; +} + +/// +/// Used to register callbacks. +/// +[SuppressMessage("Microsoft.Design", "CA1049:TypesThatOwnNativeResourcesShouldBeDisposable")] +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_CALLBACK +{ + [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] + public IntPtr CallBackProc; + public uint RefCon; + public ushort Message; +} + +/// +/// Used to register callbacks. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_CALLBACK2 +{ + [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] + public IntPtr CallBackProc; + [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] + public UIntPtr RefCon; + public ushort Message; +} + +/// +/// Used by application to get/set capability from/in a data source. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2, CharSet = CharSet.Ansi)] +public partial struct TW_CAPABILITY +{ + public CAP Cap; + public TWON ConType; + [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] + public IntPtr hContainer; +} + +/// +/// Defines a CIE XYZ space tri-stimulus value. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_CIEPOINT +{ + public TW_FIX32 X; + public TW_FIX32 Y; + public TW_FIX32 Z; +} + +/// +/// Defines the mapping from an RGB color space device into CIE 1931 (XYZ) color space. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_CIECOLOR +{ + public ushort ColorSpace; + public short LowEndian; + public short DeviceDependent; + public int VersionNumber; + public TW_TRANSFORMSTAGE StageABC; + public TW_TRANSFORMSTAGE StageLNM; + public TW_CIEPOINT WhitePoint; + public TW_CIEPOINT BlackPoint; + public TW_CIEPOINT WhitePaper; + public TW_CIEPOINT BlackInk; + public TW_FIX32 Samples; +} + +/// +/// Allows for a data source and application to pass custom data to each other. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_CUSTOMDSDATA +{ + public uint InfoLength; + [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] + public IntPtr hData; +} + +/// +/// Provides information about the Event that was raised by the Source. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public partial struct TW_DEVICEEVENT +{ + private uint _Event; + public TW_STR255 DeviceName; + public uint BatteryMinutes; + public short BatteryPercentage; + public int PowerSupply; + public TW_FIX32 XResolution; + public TW_FIX32 YResolution; + private uint _FlashUsed2; + public uint AutomaticCapture; + public uint TimeBeforeFirstCapture; + public uint TimeBetweenCaptures; +} + +/// +/// This structure holds the tri-stimulus color palette information for TW_PALETTE8 structures. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_ELEMENT8 +{ + public byte Index; + public byte Channel1; + public byte Channel2; + public byte Channel3; +} + +/// +/// DAT_ENTRYPOINT. returns essential entry points. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_ENTRYPOINT +{ + public UInt32 Size; + [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] + public IntPtr DSM_Entry; + [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] + public IntPtr DSM_MemAllocate; + [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] + public IntPtr DSM_MemFree; + [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] + public IntPtr DSM_MemLock; + [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] + public IntPtr DSM_MemUnlock; +} +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_ENTRYPOINT_LINUX64 +{ + public long Size; + [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] + public IntPtr DSM_Entry; + [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] + public IntPtr DSM_MemAllocate; + [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] + public IntPtr DSM_MemFree; + [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] + public IntPtr DSM_MemLock; + [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] + public IntPtr DSM_MemUnlock; +} +public partial struct TW_ENTRYPOINT_DELEGATES +{ + public UInt32 Size; + [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] + public IntPtr DSM_Entry; + public DSM_MEMALLOC DSM_MemAllocate; + public DSM_MEMFREE DSM_MemFree; + public DSM_MEMLOCK DSM_MemLock; + public DSM_MEMUNLOCK DSM_MemUnlock; +} +public delegate IntPtr DSM_MEMALLOC(uint size); +public delegate void DSM_MEMFREE(IntPtr handle); +public delegate IntPtr DSM_MEMLOCK(IntPtr handle); +public delegate void DSM_MEMUNLOCK(IntPtr handle); + +/// +/// Stores a group of enumerated values for a capability, the ItemList is +/// commented out so that the caller can collect information about it with +/// a marshalling call... +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_ENUMERATION +{ + public TWTY ItemType; + public uint NumItems; + public uint CurrentIndex; + public uint DefaultIndex; + //public byte[] ItemList; +} +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_ENUMERATION_LINUX64 +{ + public TWTY ItemType; + public ulong NumItems; + public ulong CurrentIndex; + public ulong DefaultIndex; + //public byte[] ItemList; +} +[StructLayout(LayoutKind.Sequential, Pack = 4)] +public struct TW_ENUMERATION_MACOSX +{ + public uint ItemType; + public uint NumItems; + public uint CurrentIndex; + public uint DefaultIndex; + //public byte[] ItemList; +} + +/// +/// Used to pass application events/messages from the application to the Source. +/// +[SuppressMessage("Microsoft.Design", "CA1049:TypesThatOwnNativeResourcesShouldBeDisposable")] +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_EVENT +{ + [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] + public IntPtr pEvent; + //public ushort TWMessage; + public MSG TWMessage; +} + +/// +/// DAT_FILTER... +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_FILTER_DESCRIPTOR +{ + public UInt32 Size; + public UInt32 HueStart; + public UInt32 HueEnd; + public UInt32 SaturationStart; + public UInt32 SaturationEnd; + public UInt32 ValueStart; + public UInt32 ValueEnd; + public UInt32 Replacement; +} + +/// +/// DAT_FILTER... +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_FILTER +{ + public UInt32 Size; + public UInt32 DescriptorCount; + public UInt32 MaxDescriptorCount; + public UInt32 Condition; + [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] + public IntPtr hDescriptors; +} + +/// +/// This structure is used to pass specific information between the data source and the application. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public partial struct TW_INFO +{ + public TWEI InfoId; + public TWTY ItemType; + public ushort NumItems; + public TWRC ReturnCode; + [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] + public UIntPtr Item; +} + +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public partial struct TW_EXTIMAGEINFO +{ + private uint NumInfos; + private TW_INFO Info_000; + private TW_INFO Info_001; + private TW_INFO Info_002; + private TW_INFO Info_003; + private TW_INFO Info_004; + private TW_INFO Info_005; + private TW_INFO Info_006; + private TW_INFO Info_007; + private TW_INFO Info_008; + private TW_INFO Info_009; + private TW_INFO Info_010; + private TW_INFO Info_011; + private TW_INFO Info_012; + private TW_INFO Info_013; + private TW_INFO Info_014; + private TW_INFO Info_015; + private TW_INFO Info_016; + private TW_INFO Info_017; + private TW_INFO Info_018; + private TW_INFO Info_019; + private TW_INFO Info_020; + private TW_INFO Info_021; + private TW_INFO Info_022; + private TW_INFO Info_023; + private TW_INFO Info_024; + private TW_INFO Info_025; + private TW_INFO Info_026; + private TW_INFO Info_027; + private TW_INFO Info_028; + private TW_INFO Info_029; + private TW_INFO Info_030; + private TW_INFO Info_031; + private TW_INFO Info_032; + private TW_INFO Info_033; + private TW_INFO Info_034; + private TW_INFO Info_035; + private TW_INFO Info_036; + private TW_INFO Info_037; + private TW_INFO Info_038; + private TW_INFO Info_039; + private TW_INFO Info_040; + private TW_INFO Info_041; + private TW_INFO Info_042; + private TW_INFO Info_043; + private TW_INFO Info_044; + private TW_INFO Info_045; + private TW_INFO Info_046; + private TW_INFO Info_047; + private TW_INFO Info_048; + private TW_INFO Info_049; + private TW_INFO Info_050; + private TW_INFO Info_051; + private TW_INFO Info_052; + private TW_INFO Info_053; + private TW_INFO Info_054; + private TW_INFO Info_055; + private TW_INFO Info_056; + private TW_INFO Info_057; + private TW_INFO Info_058; + private TW_INFO Info_059; + private TW_INFO Info_060; + private TW_INFO Info_061; + private TW_INFO Info_062; + private TW_INFO Info_063; + private TW_INFO Info_064; + private TW_INFO Info_065; + private TW_INFO Info_066; + private TW_INFO Info_067; + private TW_INFO Info_068; + private TW_INFO Info_069; + private TW_INFO Info_070; + private TW_INFO Info_071; + private TW_INFO Info_072; + private TW_INFO Info_073; + private TW_INFO Info_074; + private TW_INFO Info_075; + private TW_INFO Info_076; + private TW_INFO Info_077; + private TW_INFO Info_078; + private TW_INFO Info_079; + private TW_INFO Info_080; + private TW_INFO Info_081; + private TW_INFO Info_082; + private TW_INFO Info_083; + private TW_INFO Info_084; + private TW_INFO Info_085; + private TW_INFO Info_086; + private TW_INFO Info_087; + private TW_INFO Info_088; + private TW_INFO Info_089; + private TW_INFO Info_090; + private TW_INFO Info_091; + private TW_INFO Info_092; + private TW_INFO Info_093; + private TW_INFO Info_094; + private TW_INFO Info_095; + private TW_INFO Info_096; + private TW_INFO Info_097; + private TW_INFO Info_098; + private TW_INFO Info_099; + + // 200 seems overkill for anyone to request + // at once so I cut it down in half + + //private TW_INFO Info_100; + //private TW_INFO Info_101; + //private TW_INFO Info_102; + //private TW_INFO Info_103; + //private TW_INFO Info_104; + //private TW_INFO Info_105; + //private TW_INFO Info_106; + //private TW_INFO Info_107; + //private TW_INFO Info_108; + //private TW_INFO Info_109; + //private TW_INFO Info_110; + //private TW_INFO Info_111; + //private TW_INFO Info_112; + //private TW_INFO Info_113; + //private TW_INFO Info_114; + //private TW_INFO Info_115; + //private TW_INFO Info_116; + //private TW_INFO Info_117; + //private TW_INFO Info_118; + //private TW_INFO Info_119; + //private TW_INFO Info_120; + //private TW_INFO Info_121; + //private TW_INFO Info_122; + //private TW_INFO Info_123; + //private TW_INFO Info_124; + //private TW_INFO Info_125; + //private TW_INFO Info_126; + //private TW_INFO Info_127; + //private TW_INFO Info_128; + //private TW_INFO Info_129; + //private TW_INFO Info_130; + //private TW_INFO Info_131; + //private TW_INFO Info_132; + //private TW_INFO Info_133; + //private TW_INFO Info_134; + //private TW_INFO Info_135; + //private TW_INFO Info_136; + //private TW_INFO Info_137; + //private TW_INFO Info_138; + //private TW_INFO Info_139; + //private TW_INFO Info_140; + //private TW_INFO Info_141; + //private TW_INFO Info_142; + //private TW_INFO Info_143; + //private TW_INFO Info_144; + //private TW_INFO Info_145; + //private TW_INFO Info_146; + //private TW_INFO Info_147; + //private TW_INFO Info_148; + //private TW_INFO Info_149; + //private TW_INFO Info_150; + //private TW_INFO Info_151; + //private TW_INFO Info_152; + //private TW_INFO Info_153; + //private TW_INFO Info_154; + //private TW_INFO Info_155; + //private TW_INFO Info_156; + //private TW_INFO Info_157; + //private TW_INFO Info_158; + //private TW_INFO Info_159; + //private TW_INFO Info_160; + //private TW_INFO Info_161; + //private TW_INFO Info_162; + //private TW_INFO Info_163; + //private TW_INFO Info_164; + //private TW_INFO Info_165; + //private TW_INFO Info_166; + //private TW_INFO Info_167; + //private TW_INFO Info_168; + //private TW_INFO Info_169; + //private TW_INFO Info_170; + //private TW_INFO Info_171; + //private TW_INFO Info_172; + //private TW_INFO Info_173; + //private TW_INFO Info_174; + //private TW_INFO Info_175; + //private TW_INFO Info_176; + //private TW_INFO Info_177; + //private TW_INFO Info_178; + //private TW_INFO Info_179; + //private TW_INFO Info_180; + //private TW_INFO Info_181; + //private TW_INFO Info_182; + //private TW_INFO Info_183; + //private TW_INFO Info_184; + //private TW_INFO Info_185; + //private TW_INFO Info_186; + //private TW_INFO Info_187; + //private TW_INFO Info_188; + //private TW_INFO Info_189; + //private TW_INFO Info_190; + //private TW_INFO Info_191; + //private TW_INFO Info_192; + //private TW_INFO Info_193; + //private TW_INFO Info_194; + //private TW_INFO Info_195; + //private TW_INFO Info_196; + //private TW_INFO Info_197; + //private TW_INFO Info_198; + //private TW_INFO Info_199; + + public void Get(int a_uIndex, ref TW_INFO a_twinfo) + { + switch (a_uIndex) + { + default: return; + case 0: a_twinfo = Info_000; return; + case 1: a_twinfo = Info_001; return; + case 2: a_twinfo = Info_002; return; + case 3: a_twinfo = Info_003; return; + case 4: a_twinfo = Info_004; return; + case 5: a_twinfo = Info_005; return; + case 6: a_twinfo = Info_006; return; + case 7: a_twinfo = Info_007; return; + case 8: a_twinfo = Info_008; return; + case 9: a_twinfo = Info_009; return; + case 10: a_twinfo = Info_010; return; + case 11: a_twinfo = Info_011; return; + case 12: a_twinfo = Info_012; return; + case 13: a_twinfo = Info_013; return; + case 14: a_twinfo = Info_014; return; + case 15: a_twinfo = Info_015; return; + case 16: a_twinfo = Info_016; return; + case 17: a_twinfo = Info_017; return; + case 18: a_twinfo = Info_018; return; + case 19: a_twinfo = Info_019; return; + case 20: a_twinfo = Info_020; return; + case 21: a_twinfo = Info_021; return; + case 22: a_twinfo = Info_022; return; + case 23: a_twinfo = Info_023; return; + case 24: a_twinfo = Info_024; return; + case 25: a_twinfo = Info_025; return; + case 26: a_twinfo = Info_026; return; + case 27: a_twinfo = Info_027; return; + case 28: a_twinfo = Info_028; return; + case 29: a_twinfo = Info_029; return; + case 30: a_twinfo = Info_030; return; + case 31: a_twinfo = Info_031; return; + case 32: a_twinfo = Info_032; return; + case 33: a_twinfo = Info_033; return; + case 34: a_twinfo = Info_034; return; + case 35: a_twinfo = Info_035; return; + case 36: a_twinfo = Info_036; return; + case 37: a_twinfo = Info_037; return; + case 38: a_twinfo = Info_038; return; + case 39: a_twinfo = Info_039; return; + case 40: a_twinfo = Info_040; return; + case 41: a_twinfo = Info_041; return; + case 42: a_twinfo = Info_042; return; + case 43: a_twinfo = Info_043; return; + case 44: a_twinfo = Info_044; return; + case 45: a_twinfo = Info_045; return; + case 46: a_twinfo = Info_046; return; + case 47: a_twinfo = Info_047; return; + case 48: a_twinfo = Info_048; return; + case 49: a_twinfo = Info_049; return; + case 50: a_twinfo = Info_050; return; + case 51: a_twinfo = Info_051; return; + case 52: a_twinfo = Info_052; return; + case 53: a_twinfo = Info_053; return; + case 54: a_twinfo = Info_054; return; + case 55: a_twinfo = Info_055; return; + case 56: a_twinfo = Info_056; return; + case 57: a_twinfo = Info_057; return; + case 58: a_twinfo = Info_058; return; + case 59: a_twinfo = Info_059; return; + case 60: a_twinfo = Info_060; return; + case 61: a_twinfo = Info_061; return; + case 62: a_twinfo = Info_062; return; + case 63: a_twinfo = Info_063; return; + case 64: a_twinfo = Info_064; return; + case 65: a_twinfo = Info_065; return; + case 66: a_twinfo = Info_066; return; + case 67: a_twinfo = Info_067; return; + case 68: a_twinfo = Info_068; return; + case 69: a_twinfo = Info_069; return; + case 70: a_twinfo = Info_070; return; + case 71: a_twinfo = Info_071; return; + case 72: a_twinfo = Info_072; return; + case 73: a_twinfo = Info_073; return; + case 74: a_twinfo = Info_074; return; + case 75: a_twinfo = Info_075; return; + case 76: a_twinfo = Info_076; return; + case 77: a_twinfo = Info_077; return; + case 78: a_twinfo = Info_078; return; + case 79: a_twinfo = Info_079; return; + case 80: a_twinfo = Info_080; return; + case 81: a_twinfo = Info_081; return; + case 82: a_twinfo = Info_082; return; + case 83: a_twinfo = Info_083; return; + case 84: a_twinfo = Info_084; return; + case 85: a_twinfo = Info_085; return; + case 86: a_twinfo = Info_086; return; + case 87: a_twinfo = Info_087; return; + case 88: a_twinfo = Info_088; return; + case 89: a_twinfo = Info_089; return; + case 90: a_twinfo = Info_090; return; + case 91: a_twinfo = Info_091; return; + case 92: a_twinfo = Info_092; return; + case 93: a_twinfo = Info_093; return; + case 94: a_twinfo = Info_094; return; + case 95: a_twinfo = Info_095; return; + case 96: a_twinfo = Info_096; return; + case 97: a_twinfo = Info_097; return; + case 98: a_twinfo = Info_098; return; + case 99: a_twinfo = Info_099; return; + //case 100: a_twinfo = Info_100; return; + //case 101: a_twinfo = Info_101; return; + //case 102: a_twinfo = Info_102; return; + //case 103: a_twinfo = Info_103; return; + //case 104: a_twinfo = Info_104; return; + //case 105: a_twinfo = Info_105; return; + //case 106: a_twinfo = Info_106; return; + //case 107: a_twinfo = Info_107; return; + //case 108: a_twinfo = Info_108; return; + //case 109: a_twinfo = Info_109; return; + //case 110: a_twinfo = Info_110; return; + //case 111: a_twinfo = Info_111; return; + //case 112: a_twinfo = Info_112; return; + //case 113: a_twinfo = Info_113; return; + //case 114: a_twinfo = Info_114; return; + //case 115: a_twinfo = Info_115; return; + //case 116: a_twinfo = Info_116; return; + //case 117: a_twinfo = Info_117; return; + //case 118: a_twinfo = Info_118; return; + //case 119: a_twinfo = Info_119; return; + //case 120: a_twinfo = Info_120; return; + //case 121: a_twinfo = Info_121; return; + //case 122: a_twinfo = Info_122; return; + //case 123: a_twinfo = Info_123; return; + //case 124: a_twinfo = Info_124; return; + //case 125: a_twinfo = Info_125; return; + //case 126: a_twinfo = Info_126; return; + //case 127: a_twinfo = Info_127; return; + //case 128: a_twinfo = Info_128; return; + //case 129: a_twinfo = Info_129; return; + //case 130: a_twinfo = Info_130; return; + //case 131: a_twinfo = Info_131; return; + //case 132: a_twinfo = Info_132; return; + //case 133: a_twinfo = Info_133; return; + //case 134: a_twinfo = Info_134; return; + //case 135: a_twinfo = Info_135; return; + //case 136: a_twinfo = Info_136; return; + //case 137: a_twinfo = Info_137; return; + //case 138: a_twinfo = Info_138; return; + //case 139: a_twinfo = Info_139; return; + //case 140: a_twinfo = Info_140; return; + //case 141: a_twinfo = Info_141; return; + //case 142: a_twinfo = Info_142; return; + //case 143: a_twinfo = Info_143; return; + //case 144: a_twinfo = Info_144; return; + //case 145: a_twinfo = Info_145; return; + //case 146: a_twinfo = Info_146; return; + //case 147: a_twinfo = Info_147; return; + //case 148: a_twinfo = Info_148; return; + //case 149: a_twinfo = Info_149; return; + //case 150: a_twinfo = Info_150; return; + //case 151: a_twinfo = Info_151; return; + //case 152: a_twinfo = Info_152; return; + //case 153: a_twinfo = Info_153; return; + //case 154: a_twinfo = Info_154; return; + //case 155: a_twinfo = Info_155; return; + //case 156: a_twinfo = Info_156; return; + //case 157: a_twinfo = Info_157; return; + //case 158: a_twinfo = Info_158; return; + //case 159: a_twinfo = Info_159; return; + //case 160: a_twinfo = Info_160; return; + //case 161: a_twinfo = Info_161; return; + //case 162: a_twinfo = Info_162; return; + //case 163: a_twinfo = Info_163; return; + //case 164: a_twinfo = Info_164; return; + //case 165: a_twinfo = Info_165; return; + //case 166: a_twinfo = Info_166; return; + //case 167: a_twinfo = Info_167; return; + //case 168: a_twinfo = Info_168; return; + //case 169: a_twinfo = Info_169; return; + //case 170: a_twinfo = Info_170; return; + //case 171: a_twinfo = Info_171; return; + //case 172: a_twinfo = Info_172; return; + //case 173: a_twinfo = Info_173; return; + //case 174: a_twinfo = Info_174; return; + //case 175: a_twinfo = Info_175; return; + //case 176: a_twinfo = Info_176; return; + //case 177: a_twinfo = Info_177; return; + //case 178: a_twinfo = Info_178; return; + //case 179: a_twinfo = Info_179; return; + //case 180: a_twinfo = Info_180; return; + //case 181: a_twinfo = Info_181; return; + //case 182: a_twinfo = Info_182; return; + //case 183: a_twinfo = Info_183; return; + //case 184: a_twinfo = Info_184; return; + //case 185: a_twinfo = Info_185; return; + //case 186: a_twinfo = Info_186; return; + //case 187: a_twinfo = Info_187; return; + //case 188: a_twinfo = Info_188; return; + //case 189: a_twinfo = Info_189; return; + //case 190: a_twinfo = Info_190; return; + //case 191: a_twinfo = Info_191; return; + //case 192: a_twinfo = Info_192; return; + //case 193: a_twinfo = Info_193; return; + //case 194: a_twinfo = Info_194; return; + //case 195: a_twinfo = Info_195; return; + //case 196: a_twinfo = Info_196; return; + //case 197: a_twinfo = Info_197; return; + //case 198: a_twinfo = Info_198; return; + //case 199: a_twinfo = Info_199; return; + } + } + + public void Set(int a_uIndex, ref TW_INFO a_twinfo) + { + switch (a_uIndex) + { + default: return; + case 0: Info_000 = a_twinfo; return; + case 1: Info_001 = a_twinfo; return; + case 2: Info_002 = a_twinfo; return; + case 3: Info_003 = a_twinfo; return; + case 4: Info_004 = a_twinfo; return; + case 5: Info_005 = a_twinfo; return; + case 6: Info_006 = a_twinfo; return; + case 7: Info_007 = a_twinfo; return; + case 8: Info_008 = a_twinfo; return; + case 9: Info_009 = a_twinfo; return; + case 10: Info_010 = a_twinfo; return; + case 11: Info_011 = a_twinfo; return; + case 12: Info_012 = a_twinfo; return; + case 13: Info_013 = a_twinfo; return; + case 14: Info_014 = a_twinfo; return; + case 15: Info_015 = a_twinfo; return; + case 16: Info_016 = a_twinfo; return; + case 17: Info_017 = a_twinfo; return; + case 18: Info_018 = a_twinfo; return; + case 19: Info_019 = a_twinfo; return; + case 20: Info_020 = a_twinfo; return; + case 21: Info_021 = a_twinfo; return; + case 22: Info_022 = a_twinfo; return; + case 23: Info_023 = a_twinfo; return; + case 24: Info_024 = a_twinfo; return; + case 25: Info_025 = a_twinfo; return; + case 26: Info_026 = a_twinfo; return; + case 27: Info_027 = a_twinfo; return; + case 28: Info_028 = a_twinfo; return; + case 29: Info_029 = a_twinfo; return; + case 30: Info_030 = a_twinfo; return; + case 31: Info_031 = a_twinfo; return; + case 32: Info_032 = a_twinfo; return; + case 33: Info_033 = a_twinfo; return; + case 34: Info_034 = a_twinfo; return; + case 35: Info_035 = a_twinfo; return; + case 36: Info_036 = a_twinfo; return; + case 37: Info_037 = a_twinfo; return; + case 38: Info_038 = a_twinfo; return; + case 39: Info_039 = a_twinfo; return; + case 40: Info_040 = a_twinfo; return; + case 41: Info_041 = a_twinfo; return; + case 42: Info_042 = a_twinfo; return; + case 43: Info_043 = a_twinfo; return; + case 44: Info_044 = a_twinfo; return; + case 45: Info_045 = a_twinfo; return; + case 46: Info_046 = a_twinfo; return; + case 47: Info_047 = a_twinfo; return; + case 48: Info_048 = a_twinfo; return; + case 49: Info_049 = a_twinfo; return; + case 50: Info_050 = a_twinfo; return; + case 51: Info_051 = a_twinfo; return; + case 52: Info_052 = a_twinfo; return; + case 53: Info_053 = a_twinfo; return; + case 54: Info_054 = a_twinfo; return; + case 55: Info_055 = a_twinfo; return; + case 56: Info_056 = a_twinfo; return; + case 57: Info_057 = a_twinfo; return; + case 58: Info_058 = a_twinfo; return; + case 59: Info_059 = a_twinfo; return; + case 60: Info_060 = a_twinfo; return; + case 61: Info_061 = a_twinfo; return; + case 62: Info_062 = a_twinfo; return; + case 63: Info_063 = a_twinfo; return; + case 64: Info_064 = a_twinfo; return; + case 65: Info_065 = a_twinfo; return; + case 66: Info_066 = a_twinfo; return; + case 67: Info_067 = a_twinfo; return; + case 68: Info_068 = a_twinfo; return; + case 69: Info_069 = a_twinfo; return; + case 70: Info_070 = a_twinfo; return; + case 71: Info_071 = a_twinfo; return; + case 72: Info_072 = a_twinfo; return; + case 73: Info_073 = a_twinfo; return; + case 74: Info_074 = a_twinfo; return; + case 75: Info_075 = a_twinfo; return; + case 76: Info_076 = a_twinfo; return; + case 77: Info_077 = a_twinfo; return; + case 78: Info_078 = a_twinfo; return; + case 79: Info_079 = a_twinfo; return; + case 80: Info_080 = a_twinfo; return; + case 81: Info_081 = a_twinfo; return; + case 82: Info_082 = a_twinfo; return; + case 83: Info_083 = a_twinfo; return; + case 84: Info_084 = a_twinfo; return; + case 85: Info_085 = a_twinfo; return; + case 86: Info_086 = a_twinfo; return; + case 87: Info_087 = a_twinfo; return; + case 88: Info_088 = a_twinfo; return; + case 89: Info_089 = a_twinfo; return; + case 90: Info_090 = a_twinfo; return; + case 91: Info_091 = a_twinfo; return; + case 92: Info_092 = a_twinfo; return; + case 93: Info_093 = a_twinfo; return; + case 94: Info_094 = a_twinfo; return; + case 95: Info_095 = a_twinfo; return; + case 96: Info_096 = a_twinfo; return; + case 97: Info_097 = a_twinfo; return; + case 98: Info_098 = a_twinfo; return; + case 99: Info_099 = a_twinfo; return; + //case 100: Info_100 = a_twinfo; return; + //case 101: Info_101 = a_twinfo; return; + //case 102: Info_102 = a_twinfo; return; + //case 103: Info_103 = a_twinfo; return; + //case 104: Info_104 = a_twinfo; return; + //case 105: Info_105 = a_twinfo; return; + //case 106: Info_106 = a_twinfo; return; + //case 107: Info_107 = a_twinfo; return; + //case 108: Info_108 = a_twinfo; return; + //case 109: Info_109 = a_twinfo; return; + //case 110: Info_110 = a_twinfo; return; + //case 111: Info_111 = a_twinfo; return; + //case 112: Info_112 = a_twinfo; return; + //case 113: Info_113 = a_twinfo; return; + //case 114: Info_114 = a_twinfo; return; + //case 115: Info_115 = a_twinfo; return; + //case 116: Info_116 = a_twinfo; return; + //case 117: Info_117 = a_twinfo; return; + //case 118: Info_118 = a_twinfo; return; + //case 119: Info_119 = a_twinfo; return; + //case 120: Info_120 = a_twinfo; return; + //case 121: Info_121 = a_twinfo; return; + //case 122: Info_122 = a_twinfo; return; + //case 123: Info_123 = a_twinfo; return; + //case 124: Info_124 = a_twinfo; return; + //case 125: Info_125 = a_twinfo; return; + //case 126: Info_126 = a_twinfo; return; + //case 127: Info_127 = a_twinfo; return; + //case 128: Info_128 = a_twinfo; return; + //case 129: Info_129 = a_twinfo; return; + //case 130: Info_130 = a_twinfo; return; + //case 131: Info_131 = a_twinfo; return; + //case 132: Info_132 = a_twinfo; return; + //case 133: Info_133 = a_twinfo; return; + //case 134: Info_134 = a_twinfo; return; + //case 135: Info_135 = a_twinfo; return; + //case 136: Info_136 = a_twinfo; return; + //case 137: Info_137 = a_twinfo; return; + //case 138: Info_138 = a_twinfo; return; + //case 139: Info_139 = a_twinfo; return; + //case 140: Info_140 = a_twinfo; return; + //case 141: Info_141 = a_twinfo; return; + //case 142: Info_142 = a_twinfo; return; + //case 143: Info_143 = a_twinfo; return; + //case 144: Info_144 = a_twinfo; return; + //case 145: Info_145 = a_twinfo; return; + //case 146: Info_146 = a_twinfo; return; + //case 147: Info_147 = a_twinfo; return; + //case 148: Info_148 = a_twinfo; return; + //case 149: Info_149 = a_twinfo; return; + //case 150: Info_150 = a_twinfo; return; + //case 151: Info_151 = a_twinfo; return; + //case 152: Info_152 = a_twinfo; return; + //case 153: Info_153 = a_twinfo; return; + //case 154: Info_154 = a_twinfo; return; + //case 155: Info_155 = a_twinfo; return; + //case 156: Info_156 = a_twinfo; return; + //case 157: Info_157 = a_twinfo; return; + //case 158: Info_158 = a_twinfo; return; + //case 159: Info_159 = a_twinfo; return; + //case 160: Info_160 = a_twinfo; return; + //case 161: Info_161 = a_twinfo; return; + //case 162: Info_162 = a_twinfo; return; + //case 163: Info_163 = a_twinfo; return; + //case 164: Info_164 = a_twinfo; return; + //case 165: Info_165 = a_twinfo; return; + //case 166: Info_166 = a_twinfo; return; + //case 167: Info_167 = a_twinfo; return; + //case 168: Info_168 = a_twinfo; return; + //case 169: Info_169 = a_twinfo; return; + //case 170: Info_170 = a_twinfo; return; + //case 171: Info_171 = a_twinfo; return; + //case 172: Info_172 = a_twinfo; return; + //case 173: Info_173 = a_twinfo; return; + //case 174: Info_174 = a_twinfo; return; + //case 175: Info_175 = a_twinfo; return; + //case 176: Info_176 = a_twinfo; return; + //case 177: Info_177 = a_twinfo; return; + //case 178: Info_178 = a_twinfo; return; + //case 179: Info_179 = a_twinfo; return; + //case 180: Info_180 = a_twinfo; return; + //case 181: Info_181 = a_twinfo; return; + //case 182: Info_182 = a_twinfo; return; + //case 183: Info_183 = a_twinfo; return; + //case 184: Info_184 = a_twinfo; return; + //case 185: Info_185 = a_twinfo; return; + //case 186: Info_186 = a_twinfo; return; + //case 187: Info_187 = a_twinfo; return; + //case 188: Info_188 = a_twinfo; return; + //case 189: Info_189 = a_twinfo; return; + //case 190: Info_190 = a_twinfo; return; + //case 191: Info_191 = a_twinfo; return; + //case 192: Info_192 = a_twinfo; return; + //case 193: Info_193 = a_twinfo; return; + //case 194: Info_194 = a_twinfo; return; + //case 195: Info_195 = a_twinfo; return; + //case 196: Info_196 = a_twinfo; return; + //case 197: Info_197 = a_twinfo; return; + //case 198: Info_198 = a_twinfo; return; + //case 199: Info_199 = a_twinfo; return; + } + } +} + +/// +/// Provides information about the currently selected device. +/// TBD -- need a 32/64 bit solution for this mess +/// +[SuppressMessage("Microsoft.Portability", "CA1900:ValueTypeFieldsShouldBePortable", MessageId = "ModifiedTimeDate")] +[SuppressMessage("Microsoft.Portability", "CA1900:ValueTypeFieldsShouldBePortable", MessageId = "CreateTimeDate")] +[StructLayout(LayoutKind.Explicit, Pack = 2)] +public struct TW_FILESYSTEM +{ + [FieldOffset(0)] + public TW_STR255 InputName; + + [FieldOffset(256)] + public TW_STR255 OutputName; + + [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] + [FieldOffset(512)] + public IntPtr Context; + + [FieldOffset(520)] + public Int32 Recursive; + [FieldOffset(520)] + public UInt16 Subdirectories; + + [FieldOffset(524)] + public Int32 FileType; + [FieldOffset(524)] + public UInt32 FileSystemType; + + [FieldOffset(528)] + public UInt32 Size; + + [FieldOffset(532)] + public TW_STR32 CreateTimeDate; + + [FieldOffset(566)] + public TW_STR32 ModifiedTimeDate; + + [FieldOffset(600)] + public UInt32 FreeSpace; + + [FieldOffset(604)] + public UInt32 NewImageSize; + + [FieldOffset(608)] + public UInt32 NumberOfFiles; + + [FieldOffset(612)] + public UInt32 NumberOfSnippets; + + [FieldOffset(616)] + public UInt32 DeviceGroupMask; + + [FieldOffset(620)] + public byte Reserved; + + [FieldOffset(1127)] // 620 + 508 - 1 + private byte ReservedEnd; +} +[SuppressMessage("Microsoft.Portability", "CA1900:ValueTypeFieldsShouldBePortable", MessageId = "ModifiedTimeDate")] +[StructLayout(LayoutKind.Explicit, Pack = 2)] +public struct TW_FILESYSTEM_LEGACY +{ + [FieldOffset(0)] + public TW_STR255 InputName; + + [FieldOffset(256)] + public TW_STR255 OutputName; + + [FieldOffset(512)] + public UInt32 Context; + + [FieldOffset(516)] + public Int32 Recursive; + [FieldOffset(516)] + public UInt16 Subdirectories; + + [FieldOffset(520)] + public Int32 FileType; + [FieldOffset(520)] + public UInt32 FileSystemType; + + [FieldOffset(524)] + public UInt32 Size; + + [FieldOffset(528)] + public TW_STR32 CreateTimeDate; + + [FieldOffset(562)] + public TW_STR32 ModifiedTimeDate; + + [FieldOffset(596)] + public UInt32 FreeSpace; + + [FieldOffset(600)] + public UInt32 NewImageSize; + + [FieldOffset(604)] + public UInt32 NumberOfFiles; + + [FieldOffset(608)] + public UInt32 NumberOfSnippets; + + [FieldOffset(612)] + public UInt32 DeviceGroupMask; + + [FieldOffset(616)] + public byte Reserved; + + [FieldOffset(1123)] // 616 + 508 - 1 + private byte ReservedEnd; +} + +/// +/// This structure is used by the application to specify a set of mapping values to be applied to grayscale data. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_GRAYRESPONSE +{ + public TW_ELEMENT8 Response_00; +} + +/// +/// A general way to describe the version of software that is running. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2, CharSet = CharSet.Ansi)] +public partial struct TW_VERSION +{ + public ushort MajorNum; + public ushort MinorNum; + public TWLG Language; + public TWCY Country; + public TW_STR32 Info; +} + +/// +/// Provides identification information about a TWAIN entity. +/// The use of Padding is there to allow us to use the structure +/// with Linux 64-bit systems where the TW_INT32 and TW_UINT32 +/// types were long, and therefore 64-bits in size. This should +/// have no impact with well-behaved systems that have these types +/// as 32-bit, but should prevent memory corruption in all other +/// situations... +/// +[StructLayout(LayoutKind.Sequential, Pack = 2, CharSet = CharSet.Ansi)] +public partial struct TW_IDENTITY +{ + public ulong Id; + public TW_VERSION Version; + public ushort ProtocolMajor; + public ushort ProtocolMinor; + public uint SupportedGroups; + public TW_STR32 Manufacturer; + public TW_STR32 ProductFamily; + public TW_STR32 ProductName; +} +[StructLayout(LayoutKind.Sequential, Pack = 2, CharSet = CharSet.Ansi)] +public partial struct TW_IDENTITY_LEGACY +{ + public uint Id; + public TW_VERSION Version; + public ushort ProtocolMajor; + public ushort ProtocolMinor; + public uint SupportedGroups; + public TW_STR32 Manufacturer; + public TW_STR32 ProductFamily; + public TW_STR32 ProductName; + private UInt64 Padding; // accounts for Id and SupportedGroups +} +[StructLayout(LayoutKind.Sequential, Pack = 2, CharSet = CharSet.Ansi)] +public partial struct TW_IDENTITY_LINUX64 +{ + public ulong Id; + public TW_VERSION Version; + public ushort ProtocolMajor; + public ushort ProtocolMinor; + public ulong SupportedGroups; + public TW_STR32 Manufacturer; + public TW_STR32 ProductFamily; + public TW_STR32 ProductName; +} +[StructLayout(LayoutKind.Sequential, Pack = 2, CharSet = CharSet.Ansi)] +public partial struct TW_IDENTITY_MACOSX +{ + public uint Id; + public TW_VERSION Version; + public ushort ProtocolMajor; + public ushort ProtocolMinor; + private ushort padding; + public uint SupportedGroups; + public TW_STR32 Manufacturer; + public TW_STR32 ProductFamily; + public TW_STR32 ProductName; +} + +/// +/// Describes the “real” image data, that is, the complete image being transferred between the Source and application. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public partial struct TW_IMAGEINFO +{ + public TW_FIX32 XResolution; + public TW_FIX32 YResolution; + public int ImageWidth; + public int ImageLength; + public short SamplesPerPixel; + public short BitsPerSample_0; + public short BitsPerSample_1; + public short BitsPerSample_2; + public short BitsPerSample_3; + public short BitsPerSample_4; + public short BitsPerSample_5; + public short BitsPerSample_6; + public short BitsPerSample_7; + public short BitsPerPixel; + public TW_BOOL Planar; + public TWPT PixelType; + public TWCP Compression; +} +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_IMAGEINFO_LINUX64 +{ + public TW_FIX32 XResolution; + public TW_FIX32 YResolution; + public int ImageWidth; + public int ImageLength; + public short SamplesPerPixel; + public short BitsPerSample_0; + public short BitsPerSample_1; + public short BitsPerSample_2; + public short BitsPerSample_3; + public short BitsPerSample_4; + public short BitsPerSample_5; + public short BitsPerSample_6; + public short BitsPerSample_7; + public short BitsPerPixel; + public TW_BOOL Planar; + public TWPT PixelType; + public TWCP Compression; +} + +/// +/// Involves information about the original size of the acquired image. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_IMAGELAYOUT +{ + public TW_FRAME Frame; + public uint DocumentNumber; + public uint PageNumber; + public uint FrameNumber; +} + +/// +/// Provides information for managing memory buffers. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_MEMORY +{ + public uint Flags; + public uint Length; + [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] + public IntPtr TheMem; +} + +/// +/// Describes the form of the acquired data being passed from the Source to the application. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public partial struct TW_IMAGEMEMXFER +{ + public ushort Compression; + public uint BytesPerRow; + public uint Columns; + public uint Rows; + public uint XOffset; + public uint YOffset; + public uint BytesWritten; + public TW_MEMORY Memory; +} +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public partial struct TW_IMAGEMEMXFER_LINUX64 +{ + public ushort Compression; + public UInt64 BytesPerRow; + public UInt64 Columns; + public UInt64 Rows; + public UInt64 XOffset; + public UInt64 YOffset; + public UInt64 BytesWritten; + public UInt64 MemoryFlags; + public UInt64 MemoryLength; + [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] + public IntPtr MemoryTheMem; +} +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public partial struct TW_IMAGEMEMXFER_MACOSX +{ + public uint Compression; + public uint BytesPerRow; + public uint Columns; + public uint Rows; + public uint XOffset; + public uint YOffset; + public uint BytesWritten; + public TW_MEMORY Memory; +} + +/// +/// Describes the information necessary to transfer a JPEG-compressed image. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_JPEGCOMPRESSION +{ + public ushort ColorSpace; + public uint SubSampling; + public ushort NumComponents; + public ushort QuantMap_0; + public ushort QuantMap_1; + public ushort QuantMap_2; + public ushort QuantMap_3; + public TW_MEMORY QuantTable_0; + public TW_MEMORY QuantTable_1; + public TW_MEMORY QuantTable_2; + public TW_MEMORY QuantTable_3; + public ushort HuffmanMap_0; + public ushort HuffmanMap_1; + public ushort HuffmanMap_2; + public ushort HuffmanMap_3; + public TW_MEMORY HuffmanDC_0; + public TW_MEMORY HuffmanDC_1; + public TW_MEMORY HuffmanAC_0; + public TW_MEMORY HuffmanAC_2; +} + +/// +/// Collects scanning metrics after returning to state 4 +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_METRICS +{ + public uint SizeOf; + public uint ImageCount; + public uint SheetCount; +} + +/// +/// Stores a single value (item) which describes a capability. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_ONEVALUE +{ + public TWTY ItemType; + // public uint Item; +} +[StructLayout(LayoutKind.Sequential, Pack = 4)] +public struct TW_ONEVALUE_MACOSX +{ + public uint ItemType; + // public uint Item; +} + +/// +/// This structure holds the color palette information. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_PALETTE8 +{ + public ushort Flags; + public ushort Length; + public TW_ELEMENT8 Colors_000; +} + +/// +/// Used to bypass the TWAIN protocol when communicating with a device. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_PASSTHRU +{ + [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] + public IntPtr pCommand; + public uint CommandBytes; + public int Direction; + [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] + public IntPtr pData; + public uint DataBytes; + public uint DataBytesXfered; +} + +/// +/// This structure tells the application how many more complete transfers the Source currently has available. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_PENDINGXFERS +{ + public static TW_PENDINGXFERS DONTCARE() + { + return new TW_PENDINGXFERS { Count = -1 }; + } + + public short Count; + public uint EOJ; +} + +/// +/// Stores a range of individual values describing a capability. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_RANGE +{ + public TWTY ItemType; + public uint MinValue; + public uint MaxValue; + public uint StepSize; + public uint DefaultValue; + public uint CurrentValue; +} +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_RANGE_LINUX64 +{ + public TWTY ItemType; + public ulong MinValue; + public ulong MaxValue; + public ulong StepSize; + public ulong DefaultValue; + public ulong CurrentValue; +} +[StructLayout(LayoutKind.Sequential, Pack = 4)] +public struct TW_RANGE_MACOSX +{ + public uint ItemType; + public uint MinValue; + public uint MaxValue; + public uint StepSize; + public uint DefaultValue; + public uint CurrentValue; +} +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_RANGE_FIX32 +{ + public TWTY ItemType; + public TW_FIX32 MinValue; + public TW_FIX32 MaxValue; + public TW_FIX32 StepSize; + public TW_FIX32 DefaultValue; + public TW_FIX32 CurrentValue; +} +[StructLayout(LayoutKind.Sequential, Pack = 4)] +public struct TW_RANGE_FIX32_MACOSX +{ + public uint ItemType; + public TW_FIX32 MinValue; + public TW_FIX32 MaxValue; + public TW_FIX32 StepSize; + public TW_FIX32 DefaultValue; + public TW_FIX32 CurrentValue; +} + +/// +/// This structure is used by the application to specify a set of mapping values to be applied to RGB color data. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_RGBRESPONSE +{ + public TW_ELEMENT8 Response_00; +} + +/// +/// Describes the file format and file specification information for a transfer through a disk file. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public struct TW_SETUPFILEXFER +{ + public TW_STR255 FileName; + public TWFF Format; + public short VRefNum; +} + +/// +/// Provides the application information about the Source’s requirements and preferences regarding allocation of transfer buffer(s). +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public partial struct TW_SETUPMEMXFER +{ + public uint MinBufSize; + public uint MaxBufSize; + public uint Preferred; +} + +/// +/// Describes the status of a source. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public partial struct TW_STATUS +{ + public TWCC ConditionCode; + public ushort Data; +} + +/// +/// Translates the contents of Status into a localized UTF8string. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2)] +public partial struct TW_STATUSUTF8 +{ + public TW_STATUS Status; + public uint Size; + [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] + public IntPtr UTF8string; +} + +/// +/// Passthru for TWAIN Direct tasks. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2, CharSet = CharSet.Ansi)] +public struct TW_TWAINDIRECT +{ + public uint SizeOf; + public ushort CommunicationManager; + [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] + public IntPtr Send; + public uint SendSize; + [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] + public IntPtr Receive; + public uint ReceiveSize; +} + +/// +/// This structure is used to handle the user interface coordination between an application and a Source. +/// +[StructLayout(LayoutKind.Sequential, Pack = 2, CharSet = CharSet.Ansi)] +public struct TW_USERINTERFACE +{ + public ushort ShowUI; + public ushort ModalUI; + [SuppressMessage("Microsoft.Security", "CA2111:PointersShouldNotBeVisible")] + public IntPtr hParent; +} + +#endregion + + +/////////////////////////////////////////////////////////////////////////////// +// Generic Constants... +/////////////////////////////////////////////////////////////////////////////// +#region Generic Constants... + +/// +/// Container Types... +/// +public enum TWON : ushort +{ + ARRAY = 3, + ENUMERATION = 4, + ONEVALUE = 5, + RANGE = 6, + + ICONID = 962, + DSMID = 461, + DSMCODEID = 63, + + DONTCARE = 0xffff +} + +///// +///// Don't care values... +///// +//public const byte TWON_DONTCARE8 = 0xff; +//public const ushort TWON_DONTCARE16 = 0xff; +//public const uint TWON_DONTCARE32 = 0xffffffff; + +/// +/// Flags used in TW_MEMORY structure. +/// +[Flags] +public enum TWMF : ushort +{ + APPOWNS = 0x0001, + DSMOWNS = 0x0002, + DSOWNS = 0x0004, + POINTER = 0x0008, + HANDLE = 0x0010 +} + +/// +/// Type values... +/// +public enum TWTY : ushort +{ + Invalid = 0xffff, + + INT8 = 0x0000, + INT16 = 0x0001, + INT32 = 0x0002, + + UINT8 = 0x0003, + UINT16 = 0x0004, + UINT32 = 0x0005, + + BOOL = 0x0006, + + FIX32 = 0x0007, + + FRAME = 0x0008, + + STR32 = 0x0009, + STR64 = 0x000a, + STR128 = 0x000b, + STR255 = 0x000c, + HANDLE = 0x000f +} + +#endregion + + +/////////////////////////////////////////////////////////////////////////////// +// Capability Constants... +/////////////////////////////////////////////////////////////////////////////// +#region Capability Constants... + +/// +/// CAP_ALARMS values +/// +public enum TWAL : ushort +{ + ALARM = 0, + FEEDERERROR = 1, + FEEDERWARNING = 2, + BARCODE = 3, + DOUBLEFEED = 4, + JAM = 5, + PATCHCODE = 6, + POWER = 7, + SKEW = 8 +} + +/// +/// ICAP_AUTOSIZE values +/// +public enum TWAS : ushort +{ + NONE = 0, + AUTO = 1, + CURRENT = 2 +} + +/// +/// TWEI_BARCODEROTATION values +/// +public enum TWBCOR : ushort +{ + ROT0 = 0, + ROT90 = 1, + ROT180 = 2, + ROT270 = 3, + ROTX = 4 +} + +/// +/// ICAP_BARCODESEARCHMODE values +/// +public enum TWBD : ushort +{ + HORZ = 0, + VERT = 1, + HORZVERT = 2, + VERTHORZ = 3 +} + +/// +/// ICAP_BITORDER values +/// +public enum TWBO : ushort +{ + LSBFIRST = 0, + MSBFIRST = 1 +} + +/// +/// ICAP_AUTODISCARDBLANKPAGES values +/// +public enum TWBP : short +{ + DISABLE = -2, + AUTO = -1 +} + +/// +/// ICAP_BITDEPTHREDUCTION values +/// +public enum TWBR : ushort +{ + THRESHOLD = 0, + HALFTONE = 1, + CUSTHALFTONE = 2, + DIFFUSION = 3, + DYNAMICTHRESHOLD = 4 +} + +/// +/// ICAP_SUPPORTEDBARCODETYPES and TWEI_BARCODETYPE values +/// +public enum TWBT : ushort +{ + X3OF9 = 0, // 3OF9 in H + X2OF5INTERLEAVED = 1, // 2OF5INTERLEAVED in H + X2OF5NONINTERLEAVED = 2, // 2OF5NONINTERLEAVED in H + CODE93 = 3, + CODE128 = 4, + UCC128 = 5, + CODABAR = 6, + UPCA = 7, + UPCE = 8, + EAN8 = 9, + EAN13 = 10, + POSTNET = 11, + PDF417 = 12, + X2OF5INDUSTRIAL = 13, // 2OF5INDUSTRIAL in H + X2OF5MATRIX = 14, // 2OF5MATRIX in H + X2OF5DATALOGIC = 15, // 2OF5DATALOGIC in H + X2OF5IATA = 16, // 2OF5IATA in H + X3OF9FULLASCII = 17, // 3OF9FULLASCII in H + CODABARWITHSTARTSTOP = 18, + MAXICODE = 19, + QRCODE = 20 +} + +/// +/// ICAP_COMPRESSION values +/// +public enum TWCP : ushort +{ + NONE = 0, + PACKBITS = 1, + GROUP31D = 2, + GROUP31DEOL = 3, + GROUP32D = 4, + GROUP4 = 5, + JPEG = 6, + LZW = 7, + JBIG = 8, + PNG = 9, + RLE4 = 10, + RLE8 = 11, + BITFIELDS = 12, + ZIP = 13, + JPEG2000 = 14 +} + +/// +/// CAP_CAMERASIDE and TWEI_PAGESIDE values +/// +public enum TWCS : ushort +{ + BOTH = 0, + TOP = 1, + BOTTOM = 2 +} + +/// +/// CAP_CLEARBUFFERS values +/// +public enum TWCB : ushort +{ + AUTO = 0, + CLEAR = 1, + NOCLEAR = 2 +} + +/// +/// CAP_DEVICEEVENT values +/// +public enum TWDE : ushort +{ + CUSTOMEVENTS = 0x8000, + CHECKAUTOMATICCAPTURE = 0, + CHECKBATTERY = 1, + CHECKDEVICEONLINE = 2, + CHECKFLASH = 3, + CHECKPOWERSUPPLY = 4, + CHECKRESOLUTION = 5, + DEVICEADDED = 6, + DEVICEOFFLINE = 7, + DEVICEREADY = 8, + DEVICEREMOVED = 9, + IMAGECAPTURED = 10, + IMAGEDELETED = 11, + PAPERDOUBLEFEED = 12, + PAPERJAM = 13, + LAMPFAILURE = 14, + POWERSAVE = 15, + POWERSAVENOTIFY = 16 +} + +/// +/// TW_PASSTHRU.Direction values +/// +public enum TWDR : ushort +{ + GET = 1, + SET = 2 +} + +/// +/// TWEI_DESKEWSTATUS values +/// +public enum TWDSK : ushort +{ + SUCCESS = 0, + REPORTONLY = 1, + FAIL = 2, + DISABLED = 3 +} + +/// +/// CAP_DUPLEX values +/// +public enum TWDX : ushort +{ + NONE = 0, + X1PASSDUPLEX = 1, // 1PASSDUPLEX in H + X2PASSDUPLEX = 2 // 2PASSDUPLEX in H +} + +/// +/// CAP_FEEDERALIGNMENT values +/// +public enum TWFA : ushort +{ + NONE = 0, + LEFT = 1, + CENTER = 2, + RIGHT = 3 +} + +/// +/// ICAP_FEEDERTYPE values +/// +public enum TWFE : ushort +{ + GENERAL = 0, + PHOTO = 1 +} + +/// +/// ICAP_IMAGEFILEFORMAT values +/// +public enum TWFF : ushort +{ + TIFF = 0, + PICT = 1, + BMP = 2, + XBM = 3, + JFIF = 4, + FPX = 5, + TIFFMULTI = 6, + PNG = 7, + SPIFF = 8, + EXIF = 9, + PDF = 10, + JP2 = 11, + JPX = 13, + DEJAVU = 14, + PDFA = 15, + PDFA2 = 16, + PDFRASTER = 17, + + // KODAK + RAW = 0x8001, + RAWBMP = 0x8002 +} + +/// +/// ICAP_FLASHUSED2 values +/// +public enum TWFL : ushort +{ + NONE = 0, + OFF = 1, + ON = 2, + AUTO = 3, + REDEYE = 4 +} + +/// +/// CAP_FEEDERORDER values +/// +public enum TWFO : ushort +{ + FIRSTPAGEFIRST = 0, + LASTPAGEFIRST = 1 +} + +/// +/// CAP_FEEDERPOCKET values +/// +public enum TWFP : ushort +{ + POCKETERROR = 0, + POCKET1 = 1, + POCKET2 = 2, + POCKET3 = 3, + POCKET4 = 4, + POCKET5 = 5, + POCKET6 = 6, + POCKET7 = 7, + POCKET8 = 8, + POCKET9 = 9, + POCKET10 = 10, + POCKET11 = 11, + POCKET12 = 12, + POCKET13 = 13, + POCKET14 = 14, + POCKET15 = 15, + POCKET16 = 16 +} + +/// +/// ICAP_FLIPROTATION values +/// +public enum TWFR : ushort +{ + BOOK = 0, + FANFOLD = 1 +} + +/// +/// ICAP_FILTER values +/// +public enum TWFT : ushort +{ + RED = 0, + GREEN = 1, + BLUE = 2, + NONE = 3, + WHITE = 4, + CYAN = 5, + MAGENTA = 6, + YELLOW = 7, + BLACK = 8 +} + +/// +/// TW_FILESYSTEM.FileType values +/// +public enum TWFY : ushort +{ + CAMERA = 0, + CAMERATOP = 1, + CAMERABOTTOM = 2, + CAMERAPREVIEW = 3, + DOMAIN = 4, + HOST = 5, + DIRECTORY = 6, + IMAGE = 7, + UNKNOWN = 8 +} + +/// +/// CAP_IAFIELD*_LEVEL values +/// +public enum TWIA : ushort +{ + UNUSED = 0, + FIXED = 1, + LEVEL1 = 2, + LEVEL2 = 3, + LEVEL3 = 4, + LEVEL4 = 5 +} + +/// +/// ICAP_ICCPROFILE values +/// +public enum TWIC : ushort +{ + NONE = 0, + LINK = 1, + EMBED = 2 +} + +/// +/// ICAP_IMAGEFILTER values +/// +public enum TWIF : ushort +{ + NONE = 0, + AUTO = 1, + LOWPASS = 2, + BANDPASS = 3, + HIGHPASS = 4, + TEXT = BANDPASS, + FINELINE = HIGHPASS +} + +/// +/// ICAP_IMAGEMERGE values +/// +public enum TWIM : ushort +{ + NONE = 0, + FRONTONTOP = 1, + FRONTONBOTTOM = 2, + FRONTONLEFT = 3, + FRONTONRIGHT = 4 +} + +/// +/// CAP_JOBCONTROL values +/// +public enum TWJC : ushort +{ + NONE = 0, + JSIC = 1, + JSIS = 2, + JSXC = 3, + JSXS = 4 +} + +/// +/// ICAP_JPEGQUALITY values +/// +public enum TWJQ : short +{ + UNKNOWN = -4, + LOW = -3, + MEDIUM = -2, + HIGH = -1 +} + +/// +/// ICAP_LIGHTPATH values +/// +public enum TWLP : ushort +{ + REFLECTIVE = 0, + TRANSMISSIVE = 1 +} + +/// +/// ICAP_LIGHTSOURCE values +/// +public enum TWLS : ushort +{ + RED = 0, + GREEN = 1, + BLUE = 2, + NONE = 3, + WHITE = 4, + UV = 5, + IR = 6 +} + +/// +/// TWEI_MAGTYPE values +/// +public enum TWMD : ushort +{ + MICR = 0, + RAW = 1, + INVALID = 2 +} + +/// +/// ICAP_NOISEFILTER values +/// +public enum TWNF : ushort +{ + NONE = 0, + AUTO = 1, + LONEPIXEL = 2, + MAJORITYRULE = 3 +} + +/// +/// ICAP_ORIENTATION values +/// +public enum TWOR : ushort +{ + ROT0 = 0, + ROT90 = 1, + ROT180 = 2, + ROT270 = 3, + PORTRAIT = ROT0, + LANDSCAPE = ROT270, + AUTO = 4, + AUTOTEXT = 5, + AUTOPICTURE = 6 +} + +/// +/// ICAP_OVERSCAN values +/// +public enum TWOV : ushort +{ + NONE = 0, + AUTO = 1, + TOPBOTTOM = 2, + LEFTRIGHT = 3, + ALL = 4 +} + +/// +/// Palette types for TW_PALETTE8 +/// +public enum TWPA : ushort +{ + RGB = 0, + GRAY = 1, + CMY = 2 +} + +/// +/// ICAP_PLANARCHUNKY values +/// +public enum TWPC : ushort +{ + CHUNKY = 0, + PLANAR = 1 +} + +/// +/// TWEI_PATCHCODE values +/// +public enum TWPCH : ushort +{ + PATCH1 = 0, + PATCH2 = 1, + PATCH3 = 2, + PATCH4 = 3, + PATCH6 = 4, + PATCHT = 5 +} + +/// +/// ICAP_PIXELFLAVOR values +/// +public enum TWPF : ushort +{ + CHOCOLATE = 0, + VANILLA = 1 +} + +/// +/// CAP_PRINTERMODE values +/// +public enum TWPM : ushort +{ + SINGLESTRING = 0, + MULTISTRING = 1, + COMPOUNDSTRING = 2, + IMAGEADDRESSSTRING = 3 +} + +/// +/// CAP_PRINTER values +/// +public enum TWPR : ushort +{ + IMPRINTERTOPBEFORE = 0, + IMPRINTERTOPAFTER = 1, + IMPRINTERBOTTOMBEFORE = 2, + IMPRINTERBOTTOMAFTER = 3, + ENDORSERTOPBEFORE = 4, + ENDORSERTOPAFTER = 5, + ENDORSERBOTTOMBEFORE = 6, + ENDORSERBOTTOMAFTER = 7 +} + +/// +/// CAP_PRINTERFONTSTYLE Added 2.3 (TWPF in H) +/// +public enum TWPFS : ushort +{ + NORMAL = 0, + BOLD = 1, + ITALIC = 2, + LARGESIZE = 3, + SMALLSIZE = 4 +} + +/// +/// CAP_PRINTERINDEXTRIGGER Added 2.3 +/// +public enum TWCT : ushort +{ + PAGE = 0, + PATCH1 = 1, + PATCH2 = 2, + PATCH3 = 3, + PATCH4 = 4, + PATCHT = 5, + PATCH6 = 6 +} + +/// +/// CAP_POWERSUPPLY values +/// +public enum TWPS : ushort +{ + EXTERNAL = 0, + BATTERY = 1 +} + +/// +/// ICAP_PIXELTYPE values (PT_ means Pixel Type) +/// +public enum TWPT : ushort +{ + BW = 0, + GRAY = 1, + RGB = 2, + PALETTE = 3, + CMY = 4, + CMYK = 5, + YUV = 6, + YUVK = 7, + CIEXYZ = 8, + LAB = 9, + SRGB = 10, + SCRGB = 11, + INFRARED = 16 +} + +/// +/// CAP_SEGMENTED values +/// +public enum TWSG : ushort +{ + NONE = 0, + AUTO = 1, + MANUAL = 2 +} + +/// +/// ICAP_FILMTYPE values +/// +public enum TWFM : ushort +{ + POSITIVE = 0, + NEGATIVE = 1 +} + +/// +/// CAP_DOUBLEFEEDDETECTION values +/// +public enum TWDF : ushort +{ + ULTRASONIC = 0, + BYLENGTH = 1, + INFRARED = 2 +} + +/// +/// CAP_DOUBLEFEEDDETECTIONSENSITIVITY values +/// +public enum TWUS : ushort +{ + LOW = 0, + MEDIUM = 1, + HIGH = 2 +} + +/// +/// CAP_DOUBLEFEEDDETECTIONRESPONSE values +/// +public enum TWDP : ushort +{ + STOP = 0, + STOPANDWAIT = 1, + SOUND = 2, + DONOTIMPRINT = 3 +} + +/// +/// ICAP_MIRROR values +/// +public enum TWMR : ushort +{ + NONE = 0, + VERTICAL = 1, + HORIZONTAL = 2 +} + +/// +/// ICAP_JPEGSUBSAMPLING values +/// +public enum TWJS : ushort +{ + X444YCBCR = 0, // 444YCBCR in H + X444RGB = 1, // 444RGB in H + X422 = 2, // 422 in H + X421 = 3, // 421 in H + X411 = 4, // 411 in H + X420 = 5, // 420 in H + X410 = 6, // 410 in H + X311 = 7 // 311 in H +} + +/// +/// CAP_PAPERHANDLING values +/// +public enum TWPH : ushort +{ + NORMAL = 0, + FRAGILE = 1, + THICK = 2, + TRIFOLD = 3, + PHOTOGRAPH = 4 +} + +/// +/// CAP_INDICATORSMODE values +/// +public enum TWCI : ushort +{ + INFO = 0, + WARNING = 1, + ERROR = 2, + WARMUP = 3 +} + +/// +/// ICAP_SUPPORTEDSIZES values (SS_ means Supported Sizes) +/// +public enum TWSS : ushort +{ + NONE = 0, + A4 = 1, + JISB5 = 2, + USLETTER = 3, + USLEGAL = 4, + A5 = 5, + ISOB4 = 6, + ISOB6 = 7, + USLEDGER = 9, + USEXECUTIVE = 10, + A3 = 11, + ISOB3 = 12, + A6 = 13, + C4 = 14, + C5 = 15, + C6 = 16, + X4A0 = 17, // 4A0 in H + X2A0 = 18, // 2A0 in H + A0 = 19, + A1 = 20, + A2 = 21, + A7 = 22, + A8 = 23, + A9 = 24, + A10 = 25, + ISOB0 = 26, + ISOB1 = 27, + ISOB2 = 28, + ISOB5 = 29, + ISOB7 = 30, + ISOB8 = 31, + ISOB9 = 32, + ISOB10 = 33, + JISB0 = 34, + JISB1 = 35, + JISB2 = 36, + JISB3 = 37, + JISB4 = 38, + JISB6 = 39, + JISB7 = 40, + JISB8 = 41, + JISB9 = 42, + JISB10 = 43, + C0 = 44, + C1 = 45, + C2 = 46, + C3 = 47, + C7 = 48, + C8 = 49, + C9 = 50, + C10 = 51, + USSTATEMENT = 52, + BUSINESSCARD = 53, + MAXSIZE = 54 +} + +/// +/// ICAP_XFERMECH values (SX_ means Setup XFer) +/// +public enum TWSX : ushort +{ + NATIVE = 0, + FILE = 1, + MEMORY = 2, + MEMFILE = 4 +} + +/// +/// ICAP_UNITS values (UN_ means UNits) +/// +public enum TWUN : ushort +{ + INCHES = 0, + CENTIMETERS = 1, + PICAS = 2, + POINTS = 3, + TWIPS = 4, + PIXELS = 5, + MILLIMETERS = 6 +} + +/// +/// Country Constants +/// +public enum TWCY : ushort +{ + AFGHANISTAN = 1001, + ALGERIA = 213, + AMERICANSAMOA = 684, + ANDORRA = 33, + ANGOLA = 1002, + ANGUILLA = 8090, + ANTIGUA = 8091, + ARGENTINA = 54, + ARUBA = 297, + ASCENSIONI = 247, + AUSTRALIA = 61, + AUSTRIA = 43, + BAHAMAS = 8092, + BAHRAIN = 973, + BANGLADESH = 880, + BARBADOS = 8093, + BELGIUM = 32, + BELIZE = 501, + BENIN = 229, + BERMUDA = 8094, + BHUTAN = 1003, + BOLIVIA = 591, + BOTSWANA = 267, + BRITAIN = 6, + BRITVIRGINIS = 8095, + BRAZIL = 55, + BRUNEI = 673, + BULGARIA = 359, + BURKINAFASO = 1004, + BURMA = 1005, + BURUNDI = 1006, + CAMAROON = 237, + CANADA = 2, + CAPEVERDEIS = 238, + CAYMANIS = 8096, + CENTRALAFREP = 1007, + CHAD = 1008, + CHILE = 56, + CHINA = 86, + CHRISTMASIS = 1009, + COCOSIS = 1009, + COLOMBIA = 57, + COMOROS = 1010, + CONGO = 1011, + COOKIS = 1012, + COSTARICA = 506, + CUBA = 5, + CYPRUS = 357, + CZECHOSLOVAKIA = 42, + DENMARK = 45, + DJIBOUTI = 1013, + DOMINICA = 8097, + DOMINCANREP = 8098, + EASTERIS = 1014, + ECUADOR = 593, + EGYPT = 20, + ELSALVADOR = 503, + EQGUINEA = 1015, + ETHIOPIA = 251, + FALKLANDIS = 1016, + FAEROEIS = 298, + FIJIISLANDS = 679, + FINLAND = 358, + FRANCE = 33, + FRANTILLES = 596, + FRGUIANA = 594, + FRPOLYNEISA = 689, + FUTANAIS = 1043, + GABON = 241, + GAMBIA = 220, + GERMANY = 49, + GHANA = 233, + GIBRALTER = 350, + GREECE = 30, + GREENLAND = 299, + GRENADA = 8099, + GRENEDINES = 8015, + GUADELOUPE = 590, + GUAM = 671, + GUANTANAMOBAY = 5399, + GUATEMALA = 502, + GUINEA = 224, + GUINEABISSAU = 1017, + GUYANA = 592, + HAITI = 509, + HONDURAS = 504, + HONGKONG = 852, + HUNGARY = 36, + ICELAND = 354, + INDIA = 91, + INDONESIA = 62, + IRAN = 98, + IRAQ = 964, + IRELAND = 353, + ISRAEL = 972, + ITALY = 39, + IVORYCOAST = 225, + JAMAICA = 8010, + JAPAN = 81, + JORDAN = 962, + KENYA = 254, + KIRIBATI = 1018, + KOREA = 82, + KUWAIT = 965, + LAOS = 1019, + LEBANON = 1020, + LIBERIA = 231, + LIBYA = 218, + LIECHTENSTEIN = 41, + LUXENBOURG = 352, + MACAO = 853, + MADAGASCAR = 1021, + MALAWI = 265, + MALAYSIA = 60, + MALDIVES = 960, + MALI = 1022, + MALTA = 356, + MARSHALLIS = 692, + MAURITANIA = 1023, + MAURITIUS = 230, + MEXICO = 3, + MICRONESIA = 691, + MIQUELON = 508, + MONACO = 33, + MONGOLIA = 1024, + MONTSERRAT = 8011, + MOROCCO = 212, + MOZAMBIQUE = 1025, + NAMIBIA = 264, + NAURU = 1026, + NEPAL = 977, + NETHERLANDS = 31, + NETHANTILLES = 599, + NEVIS = 8012, + NEWCALEDONIA = 687, + NEWZEALAND = 64, + NICARAGUA = 505, + NIGER = 227, + NIGERIA = 234, + NIUE = 1027, + NORFOLKI = 1028, + NORWAY = 47, + OMAN = 968, + PAKISTAN = 92, + PALAU = 1029, + PANAMA = 507, + PARAGUAY = 595, + PERU = 51, + PHILLIPPINES = 63, + PITCAIRNIS = 1030, + PNEWGUINEA = 675, + POLAND = 48, + PORTUGAL = 351, + QATAR = 974, + REUNIONI = 1031, + ROMANIA = 40, + RWANDA = 250, + SAIPAN = 670, + SANMARINO = 39, + SAOTOME = 1033, + SAUDIARABIA = 966, + SENEGAL = 221, + SEYCHELLESIS = 1034, + SIERRALEONE = 1035, + SINGAPORE = 65, + SOLOMONIS = 1036, + SOMALI = 1037, + SOUTHAFRICA = 27, + SPAIN = 34, + SRILANKA = 94, + STHELENA = 1032, + STKITTS = 8013, + STLUCIA = 8014, + STPIERRE = 508, + STVINCENT = 8015, + SUDAN = 1038, + SURINAME = 597, + SWAZILAND = 268, + SWEDEN = 46, + SWITZERLAND = 41, + SYRIA = 1039, + TAIWAN = 886, + TANZANIA = 255, + THAILAND = 66, + TOBAGO = 8016, + TOGO = 228, + TONGAIS = 676, + TRINIDAD = 8016, + TUNISIA = 216, + TURKEY = 90, + TURKSCAICOS = 8017, + TUVALU = 1040, + UGANDA = 256, + USSR = 7, + UAEMIRATES = 971, + UNITEDKINGDOM = 44, + USA = 1, + URUGUAY = 598, + VANUATU = 1041, + VATICANCITY = 39, + VENEZUELA = 58, + WAKE = 1042, + WALLISIS = 1043, + WESTERNSAHARA = 1044, + WESTERNSAMOA = 1045, + YEMEN = 1046, + YUGOSLAVIA = 38, + ZAIRE = 243, + ZAMBIA = 260, + ZIMBABWE = 263, + ALBANIA = 355, + ARMENIA = 374, + AZERBAIJAN = 994, + BELARUS = 375, + BOSNIAHERZGO = 387, + CAMBODIA = 855, + CROATIA = 385, + CZECHREPUBLIC = 420, + DIEGOGARCIA = 246, + ERITREA = 291, + ESTONIA = 372, + GEORGIA = 995, + LATVIA = 371, + LESOTHO = 266, + LITHUANIA = 370, + MACEDONIA = 389, + MAYOTTEIS = 269, + MOLDOVA = 373, + MYANMAR = 95, + NORTHKOREA = 850, + PUERTORICO = 787, + RUSSIA = 7, + SERBIA = 381, + SLOVAKIA = 421, + SLOVENIA = 386, + SOUTHKOREA = 82, + UKRAINE = 380, + USVIRGINIS = 340, + VIETNAM = 84 +} + +/// +/// Language Constants +/// +public enum TWLG : short +{ + USERLOCALE = -1, + DAN = 0, + DUT = 1, + ENG = 2, + FCF = 3, + FIN = 4, + FRN = 5, + GER = 6, + ICE = 7, + ITN = 8, + NOR = 9, + POR = 10, + SPA = 11, + SWE = 12, + USA = 13, + AFRIKAANS = 14, + ALBANIA = 15, + ARABIC = 16, + ARABIC_ALGERIA = 17, + ARABIC_BAHRAIN = 18, + ARABIC_EGYPT = 19, + ARABIC_IRAQ = 20, + ARABIC_JORDAN = 21, + ARABIC_KUWAIT = 22, + ARABIC_LEBANON = 23, + ARABIC_LIBYA = 24, + ARABIC_MOROCCO = 25, + ARABIC_OMAN = 26, + ARABIC_QATAR = 27, + ARABIC_SAUDIARABIA = 28, + ARABIC_SYRIA = 29, + ARABIC_TUNISIA = 30, + ARABIC_UAE = 31, + ARABIC_YEMEN = 32, + BASQUE = 33, + BYELORUSSIAN = 34, + BULGARIAN = 35, + CATALAN = 36, + CHINESE = 37, + CHINESE_HONGKONG = 38, + CHINESE_PRC = 39, + CHINESE_SINGAPORE = 40, + CHINESE_SIMPLIFIED = 41, + CHINESE_TAIWAN = 42, + CHINESE_TRADITIONAL = 43, + CROATIA = 44, + CZECH = 45, + DANISH = DAN, + DUTCH = DUT, + DUTCH_BELGIAN = 46, + ENGLISH = ENG, + ENGLISH_AUSTRALIAN = 47, + ENGLISH_CANADIAN = 48, + ENGLISH_IRELAND = 49, + ENGLISH_NEWZEALAND = 50, + ENGLISH_SOUTHAFRICA = 51, + ENGLISH_UK = 52, + ENGLISH_USA = USA, + ESTONIAN = 53, + FAEROESE = 54, + FARSI = 55, + FINNISH = FIN, + FRENCH = FRN, + FRENCH_BELGIAN = 56, + FRENCH_CANADIAN = FCF, + FRENCH_LUXEMBOURG = 57, + FRENCH_SWISS = 58, + GERMAN = GER, + GERMAN_AUSTRIAN = 59, + GERMAN_LUXEMBOURG = 60, + GERMAN_LIECHTENSTEIN = 61, + GERMAN_SWISS = 62, + GREEK = 63, + HEBREW = 64, + HUNGARIAN = 65, + ICELANDIC = ICE, + INDONESIAN = 66, + ITALIAN = ITN, + ITALIAN_SWISS = 67, + JAPANESE = 68, + KOREAN = 69, + KOREAN_JOHAB = 70, + LATVIAN = 71, + LITHUANIAN = 72, + NORWEGIAN = NOR, + NORWEGIAN_BOKMAL = 73, + NORWEGIAN_NYNORSK = 74, + POLISH = 75, + PORTUGUESE = POR, + PORTUGUESE_BRAZIL = 76, + ROMANIAN = 77, + RUSSIAN = 78, + SERBIAN_LATIN = 79, + SLOVAK = 80, + SLOVENIAN = 81, + SPANISH = TWLG.SPA, + SPANISH_MEXICAN = 82, + SPANISH_MODERN = 83, + SWEDISH = TWLG.SWE, + THAI = 84, + TURKISH = 85, + UKRANIAN = 86, + ASSAMESE = 87, + BENGALI = 88, + BIHARI = 89, + BODO = 90, + DOGRI = 91, + GUJARATI = 92, + HARYANVI = 93, + HINDI = 94, + KANNADA = 95, + KASHMIRI = 96, + MALAYALAM = 97, + MARATHI = 98, + MARWARI = 99, + MEGHALAYAN = 100, + MIZO = 101, + NAGA = 102, + ORISSI = 103, + PUNJABI = 104, + PUSHTU = 105, + SERBIAN_CYRILLIC = 106, + SIKKIMI = 107, + SWEDISH_FINLAND = 108, + TAMIL = 109, + TELUGU = 110, + TRIPURI = 111, + URDU = 112, + VIETNAMESE = 113 + //NOTE: when adding to this list, also update Language->Set() +} + +#endregion + + +/////////////////////////////////////////////////////////////////////////////// +// Data Groups... +/////////////////////////////////////////////////////////////////////////////// +#region Data Groups... + +/// +/// Data Groups... +/// +[Flags] +public enum DG : uint +{ + CONTROL = 0x1, + IMAGE = 0x2, + AUDIO = 0x4, + + // More Data Functionality may be added in the future. + // These are for items that need to be determined before DS is opened. + // NOTE: Supported Functionality constants must be powers of 2 as they are + // used as bitflags when Application asks DSM to present a list of DSs. + // to support backward capability the App and DS will not use the fields + DSM2 = 0x10000000, + APP2 = 0x20000000, + DS2 = 0x40000000, + MASK = 0xFFFF +} + +#endregion + + +/////////////////////////////////////////////////////////////////////////////// +// Data Argument Types... +/////////////////////////////////////////////////////////////////////////////// +#region Data Argument Types... + +/// +/// Data Argument Types... +/// +public enum DAT : ushort +{ + // NULL and Custom Base... + NULL = 0x0, + CUSTOM = 0x8000, + + // Data Argument Types for the DG_CONTROL Data Group. + CAPABILITY = 0x1, + EVENT = 0x2, + IDENTITY = 0x3, + PARENT = 0x4, + PENDINGXFERS = 0x5, + SETUPMEMXFER = 0x6, + SETUPFILEXFER = 0x7, + STATUS = 0x8, + USERINTERFACE = 0x9, + XFERGROUP = 0xa, + CUSTOMDSDATA = 0xc, + DEVICEEVENT = 0xd, + FILESYSTEM = 0xe, + PASSTHRU = 0xf, + CALLBACK = 0x10, + STATUSUTF8 = 0x11, + CALLBACK2 = 0x12, + METRICS = 0x13, + TWAINDIRECT = 0x14, + + // Data Argument Types for the DG_IMAGE Data Group. + IMAGEINFO = 0x0101, + IMAGELAYOUT = 0x0102, + IMAGEMEMXFER = 0x0103, + IMAGENATIVEXFER = 0x0104, + IMAGEFILEXFER = 0x105, + CIECOLOR = 0x106, + GRAYRESPONSE = 0x107, + RGBRESPONSE = 0x108, + JPEGCOMPRESSION = 0x109, + PALETTE8 = 0x10a, + EXTIMAGEINFO = 0x10b, + FILTER = 0x10c, + + /* Data Argument Types for the DG_AUDIO Data Group. */ + AUDIOFILEXFER = 0x201, + AUDIOINFO = 0x202, + AUDIONATIVEXFER = 0x203, + + /* misplaced */ + ICCPROFILE = 0x401, + IMAGEMEMFILEXFER = 0x402, + ENTRYPOINT = 0x403 +} + +#endregion + + +/////////////////////////////////////////////////////////////////////////////// +// Messages... +/////////////////////////////////////////////////////////////////////////////// +#region Messages... + +/// +/// All message constants are unique. +/// Messages are grouped according to which DATs they are used with. +/// +public enum MSG : ushort +{ + // Only used to clear fields... + NULL = 0x0, + + // Generic messages may be used with any of several DATs. + GET = 0x1, + GETCURRENT = 0x2, + GETDEFAULT = 0x3, + GETFIRST = 0x4, + GETNEXT = 0x5, + SET = 0x6, + RESET = 0x7, + QUERYSUPPORT = 0x8, + GETHELP = 0x9, + GETLABEL = 0xa, + GETLABELENUM = 0xb, + SETCONSTRAINT = 0xc, + + // Messages used with DAT_NULL. + XFERREADY = 0x101, + CLOSEDSREQ = 0x102, + CLOSEDSOK = 0x103, + DEVICEEVENT = 0x104, + + // Messages used with a pointer to DAT_PARENT data. + OPENDSM = 0x301, + CLOSEDSM = 0x302, + + // Messages used with a pointer to a DAT_IDENTITY structure. + OPENDS = 0x401, + CLOSEDS = 0x402, + USERSELECT = 0x403, + + // Messages used with a pointer to a DAT_USERINTERFACE structure. + DISABLEDS = 0x501, + ENABLEDS = 0x502, + ENABLEDSUIONLY = 0x503, + + // Messages used with a pointer to a DAT_EVENT structure. + PROCESSEVENT = 0x601, + + // Messages used with a pointer to a DAT_PENDINGXFERS structure + ENDXFER = 0x701, + STOPFEEDER = 0x702, + + // Messages used with a pointer to a DAT_FILESYSTEM structure + CHANGEDIRECTORY = 0x0801, + CREATEDIRECTORY = 0x0802, + DELETE = 0x0803, + FORMATMEDIA = 0x0804, + GETCLOSE = 0x0805, + GETFIRSTFILE = 0x0806, + GETINFO = 0x0807, + GETNEXTFILE = 0x0808, + RENAME = 0x0809, + COPY = 0x080A, + AUTOMATICCAPTUREDIRECTORY = 0x080B, + + // Messages used with a pointer to a DAT_PASSTHRU structure + PASSTHRU = 0x0901, + + // used with DAT_CALLBACK + REGISTER_CALLBACK = 0x0902, + + // used with DAT_CAPABILITY + RESETALL = 0x0A01, + + // used with DAT_TWAINDIRECT + SETTASK = 0x0B01, +} + +#endregion + + +/////////////////////////////////////////////////////////////////////////////// +// Capabilities... +/////////////////////////////////////////////////////////////////////////////// +#region Capabilities... + +/// +/// The naming convention is a little awkward, but it allows us to +/// achieve a unified capability type... +/// +public enum CAP : ushort +{ + // Base of custom capabilities. + CAP_CUSTOMBASE = 0x8000, + + /* all data sources are REQUIRED to support these caps */ + CAP_XFERCOUNT = 0x0001, + + /* image data sources are REQUIRED to support these caps */ + ICAP_COMPRESSION = 0x0100, + ICAP_PIXELTYPE = 0x0101, + ICAP_UNITS = 0x0102, + ICAP_XFERMECH = 0x0103, + + // all data sources MAY support these caps. + CAP_AUTHOR = 0x1000, + CAP_CAPTION = 0x1001, + CAP_FEEDERENABLED = 0x1002, + CAP_FEEDERLOADED = 0x1003, + CAP_TIMEDATE = 0x1004, + CAP_SUPPORTEDCAPS = 0x1005, + CAP_EXTENDEDCAPS = 0x1006, + CAP_AUTOFEED = 0x1007, + CAP_CLEARPAGE = 0x1008, + CAP_FEEDPAGE = 0x1009, + CAP_REWINDPAGE = 0x100a, + CAP_INDICATORS = 0x100b, + CAP_PAPERDETECTABLE = 0x100d, + CAP_UICONTROLLABLE = 0x100e, + CAP_DEVICEONLINE = 0x100f, + CAP_AUTOSCAN = 0x1010, + CAP_THUMBNAILSENABLED = 0x1011, + CAP_DUPLEX = 0x1012, + CAP_DUPLEXENABLED = 0x1013, + CAP_ENABLEDSUIONLY = 0x1014, + CAP_CUSTOMDSDATA = 0x1015, + CAP_ENDORSER = 0x1016, + CAP_JOBCONTROL = 0x1017, + CAP_ALARMS = 0x1018, + CAP_ALARMVOLUME = 0x1019, + CAP_AUTOMATICCAPTURE = 0x101a, + CAP_TIMEBEFOREFIRSTCAPTURE = 0x101b, + CAP_TIMEBETWEENCAPTURES = 0x101c, + CAP_CLEARBUFFERS = 0x101d, + CAP_MAXBATCHBUFFERS = 0x101e, + CAP_DEVICETIMEDATE = 0x101f, + CAP_POWERSUPPLY = 0x1020, + CAP_CAMERAPREVIEWUI = 0x1021, + CAP_DEVICEEVENT = 0x1022, + CAP_SERIALNUMBER = 0x1024, + CAP_PRINTER = 0x1026, + CAP_PRINTERENABLED = 0x1027, + CAP_PRINTERINDEX = 0x1028, + CAP_PRINTERMODE = 0x1029, + CAP_PRINTERSTRING = 0x102a, + CAP_PRINTERSUFFIX = 0x102b, + CAP_LANGUAGE = 0x102c, + CAP_FEEDERALIGNMENT = 0x102d, + CAP_FEEDERORDER = 0x102e, + CAP_REACQUIREALLOWED = 0x1030, + CAP_BATTERYMINUTES = 0x1032, + CAP_BATTERYPERCENTAGE = 0x1033, + CAP_CAMERASIDE = 0x1034, + CAP_SEGMENTED = 0x1035, + CAP_CAMERAENABLED = 0x1036, + CAP_CAMERAORDER = 0x1037, + CAP_MICRENABLED = 0x1038, + CAP_FEEDERPREP = 0x1039, + CAP_FEEDERPOCKET = 0x103a, + CAP_AUTOMATICSENSEMEDIUM = 0x103b, + CAP_CUSTOMINTERFACEGUID = 0x103c, + CAP_SUPPORTEDCAPSSEGMENTUNIQUE = 0x103d, + CAP_SUPPORTEDDATS = 0x103e, + CAP_DOUBLEFEEDDETECTION = 0x103f, + CAP_DOUBLEFEEDDETECTIONLENGTH = 0x1040, + CAP_DOUBLEFEEDDETECTIONSENSITIVITY = 0x1041, + CAP_DOUBLEFEEDDETECTIONRESPONSE = 0x1042, + CAP_PAPERHANDLING = 0x1043, + CAP_INDICATORSMODE = 0x1044, + CAP_PRINTERVERTICALOFFSET = 0x1045, + CAP_POWERSAVETIME = 0x1046, + CAP_PRINTERCHARROTATION = 0x1047, + CAP_PRINTERFONTSTYLE = 0x1048, + CAP_PRINTERINDEXLEADCHAR = 0x1049, + CAP_PRINTERINDEXMAXVALUE = 0x104A, + CAP_PRINTERINDEXNUMDIGITS = 0x104B, + CAP_PRINTERINDEXSTEP = 0x104C, + CAP_PRINTERINDEXTRIGGER = 0x104D, + CAP_PRINTERSTRINGPREVIEW = 0x104E, + CAP_SHEETCOUNT = 0x104F, + CAP_IMAGEADDRESSENABLED = 0x1050, + CAP_IAFIELDA_LEVEL = 0x1051, + CAP_IAFIELDB_LEVEL = 0x1052, + CAP_IAFIELDC_LEVEL = 0x1053, + CAP_IAFIELDD_LEVEL = 0x1054, + CAP_IAFIELDE_LEVEL = 0x1055, + CAP_IAFIELDA_PRINTFORMAT = 0x1056, + CAP_IAFIELDB_PRINTFORMAT = 0x1057, + CAP_IAFIELDC_PRINTFORMAT = 0x1058, + CAP_IAFIELDD_PRINTFORMAT = 0x1059, + CAP_IAFIELDE_PRINTFORMAT = 0x105A, + CAP_IAFIELDA_VALUE = 0x105B, + CAP_IAFIELDB_VALUE = 0x105C, + CAP_IAFIELDC_VALUE = 0x105D, + CAP_IAFIELDD_VALUE = 0x105E, + CAP_IAFIELDE_VALUE = 0x105F, + CAP_IAFIELDA_LASTPAGE = 0x1060, + CAP_IAFIELDB_LASTPAGE = 0x1061, + CAP_IAFIELDC_LASTPAGE = 0x1062, + CAP_IAFIELDD_LASTPAGE = 0x1063, + CAP_IAFIELDE_LASTPAGE = 0x1064, + + // image data sources MAY support these caps. + ICAP_AUTOBRIGHT = 0x1100, + ICAP_BRIGHTNESS = 0x1101, + ICAP_CONTRAST = 0x1103, + ICAP_CUSTHALFTONE = 0x1104, + ICAP_EXPOSURETIME = 0x1105, + ICAP_FILTER = 0x1106, + ICAP_FLASHUSED = 0x1107, + ICAP_GAMMA = 0x1108, + ICAP_HALFTONES = 0x1109, + ICAP_HIGHLIGHT = 0x110a, + ICAP_IMAGEFILEFORMAT = 0x110c, + ICAP_LAMPSTATE = 0x110d, + ICAP_LIGHTSOURCE = 0x110e, + ICAP_ORIENTATION = 0x1110, + ICAP_PHYSICALWIDTH = 0x1111, + ICAP_PHYSICALHEIGHT = 0x1112, + ICAP_SHADOW = 0x1113, + ICAP_FRAMES = 0x1114, + ICAP_XNATIVERESOLUTION = 0x1116, + ICAP_YNATIVERESOLUTION = 0x1117, + ICAP_XRESOLUTION = 0x1118, + ICAP_YRESOLUTION = 0x1119, + ICAP_MAXFRAMES = 0x111a, + ICAP_TILES = 0x111b, + ICAP_BITORDER = 0x111c, + ICAP_CCITTKFACTOR = 0x111d, + ICAP_LIGHTPATH = 0x111e, + ICAP_PIXELFLAVOR = 0x111f, + ICAP_PLANARCHUNKY = 0x1120, + ICAP_ROTATION = 0x1121, + ICAP_SUPPORTEDSIZES = 0x1122, + ICAP_THRESHOLD = 0x1123, + ICAP_XSCALING = 0x1124, + ICAP_YSCALING = 0x1125, + ICAP_BITORDERCODES = 0x1126, + ICAP_PIXELFLAVORCODES = 0x1127, + ICAP_JPEGPIXELTYPE = 0x1128, + ICAP_TIMEFILL = 0x112a, + ICAP_BITDEPTH = 0x112b, + ICAP_BITDEPTHREDUCTION = 0x112c, + ICAP_UNDEFINEDIMAGESIZE = 0x112d, + ICAP_IMAGEDATASET = 0x112e, + ICAP_EXTIMAGEINFO = 0x112f, + ICAP_MINIMUMHEIGHT = 0x1130, + ICAP_MINIMUMWIDTH = 0x1131, + ICAP_AUTODISCARDBLANKPAGES = 0x1134, + ICAP_FLIPROTATION = 0x1136, + ICAP_BARCODEDETECTIONENABLED = 0x1137, + ICAP_SUPPORTEDBARCODETYPES = 0x1138, + ICAP_BARCODEMAXSEARCHPRIORITIES = 0x1139, + ICAP_BARCODESEARCHPRIORITIES = 0x113a, + ICAP_BARCODESEARCHMODE = 0x113b, + ICAP_BARCODEMAXRETRIES = 0x113c, + ICAP_BARCODETIMEOUT = 0x113d, + ICAP_ZOOMFACTOR = 0x113e, + ICAP_PATCHCODEDETECTIONENABLED = 0x113f, + ICAP_SUPPORTEDPATCHCODETYPES = 0x1140, + ICAP_PATCHCODEMAXSEARCHPRIORITIES = 0x1141, + ICAP_PATCHCODESEARCHPRIORITIES = 0x1142, + ICAP_PATCHCODESEARCHMODE = 0x1143, + ICAP_PATCHCODEMAXRETRIES = 0x1144, + ICAP_PATCHCODETIMEOUT = 0x1145, + ICAP_FLASHUSED2 = 0x1146, + ICAP_IMAGEFILTER = 0x1147, + ICAP_NOISEFILTER = 0x1148, + ICAP_OVERSCAN = 0x1149, + ICAP_AUTOMATICBORDERDETECTION = 0x1150, + ICAP_AUTOMATICDESKEW = 0x1151, + ICAP_AUTOMATICROTATE = 0x1152, + ICAP_JPEGQUALITY = 0x1153, + ICAP_FEEDERTYPE = 0x1154, + ICAP_ICCPROFILE = 0x1155, + ICAP_AUTOSIZE = 0x1156, + ICAP_AUTOMATICCROPUSESFRAME = 0x1157, + ICAP_AUTOMATICLENGTHDETECTION = 0x1158, + ICAP_AUTOMATICCOLORENABLED = 0x1159, + ICAP_AUTOMATICCOLORNONCOLORPIXELTYPE = 0x115a, + ICAP_COLORMANAGEMENTENABLED = 0x115b, + ICAP_IMAGEMERGE = 0x115c, + ICAP_IMAGEMERGEHEIGHTTHRESHOLD = 0x115d, + ICAP_SUPPORTEDEXTIMAGEINFO = 0x115e, + ICAP_FILMTYPE = 0x115f, + ICAP_MIRROR = 0x1160, + ICAP_JPEGSUBSAMPLING = 0x1161, + + // image data sources MAY support these audio caps. + ACAP_XFERMECH = 0x1202 +} + +#endregion + + +/////////////////////////////////////////////////////////////////////////////// +// Extended Image Info Attributes section Added 1.7... +/////////////////////////////////////////////////////////////////////////////// +#region Extended Image Info Attributes section Added 1.7... + +/// +/// Extended Image Info Attributes... +/// +public enum TWEI : ushort +{ + BARCODEX = 0x1200, + BARCODEY = 0x1201, + BARCODETEXT = 0x1202, + BARCODETYPE = 0x1203, + DESHADETOP = 0x1204, + DESHADELEFT = 0x1205, + DESHADEHEIGHT = 0x1206, + DESHADEWIDTH = 0x1207, + DESHADESIZE = 0x1208, + SPECKLESREMOVED = 0x1209, + HORZLINEXCOORD = 0x120A, + HORZLINEYCOORD = 0x120B, + HORZLINELENGTH = 0x120C, + HORZLINETHICKNESS = 0x120D, + VERTLINEXCOORD = 0x120E, + VERTLINEYCOORD = 0x120F, + VERTLINELENGTH = 0x1210, + VERTLINETHICKNESS = 0x1211, + PATCHCODE = 0x1212, + ENDORSEDTEXT = 0x1213, + FORMCONFIDENCE = 0x1214, + FORMTEMPLATEMATCH = 0x1215, + FORMTEMPLATEPAGEMATCH = 0x1216, + FORMHORZDOCOFFSET = 0x1217, + FORMVERTDOCOFFSET = 0x1218, + BARCODECOUNT = 0x1219, + BARCODECONFIDENCE = 0x121A, + BARCODEROTATION = 0x121B, + BARCODETEXTLENGTH = 0x121C, + DESHADECOUNT = 0x121D, + DESHADEBLACKCOUNTOLD = 0x121E, + DESHADEBLACKCOUNTNEW = 0x121F, + DESHADEBLACKRLMIN = 0x1220, + DESHADEBLACKRLMAX = 0x1221, + DESHADEWHITECOUNTOLD = 0x1222, + DESHADEWHITECOUNTNEW = 0x1223, + DESHADEWHITERLMIN = 0x1224, + DESHADEWHITERLAVE = 0x1225, + DESHADEWHITERLMAX = 0x1226, + BLACKSPECKLESREMOVED = 0x1227, + WHITESPECKLESREMOVED = 0x1228, + HORZLINECOUNT = 0x1229, + VERTLINECOUNT = 0x122A, + DESKEWSTATUS = 0x122B, + SKEWORIGINALANGLE = 0x122C, + SKEWFINALANGLE = 0x122D, + SKEWCONFIDENCE = 0x122E, + SKEWWINDOWX1 = 0x122F, + SKEWWINDOWY1 = 0x1230, + SKEWWINDOWX2 = 0x1231, + SKEWWINDOWY2 = 0x1232, + SKEWWINDOWX3 = 0x1233, + SKEWWINDOWY3 = 0x1234, + SKEWWINDOWX4 = 0x1235, + SKEWWINDOWY4 = 0x1236, + BOOKNAME = 0x1238, + CHAPTERNUMBER = 0x1239, + DOCUMENTNUMBER = 0x123A, + PAGENUMBER = 0x123B, + CAMERA = 0x123C, + FRAMENUMBER = 0x123D, + FRAME = 0x123E, + PIXELFLAVOR = 0x123F, + ICCPROFILE = 0x1240, + LASTSEGMENT = 0x1241, + SEGMENTNUMBER = 0x1242, + MAGDATA = 0x1243, + MAGTYPE = 0x1244, + PAGESIDE = 0x1245, + FILESYSTEMSOURCE = 0x1246, + IMAGEMERGED = 0x1247, + MAGDATALENGTH = 0x1248, + PAPERCOUNT = 0x1249, + PRINTERTEXT = 0x124A, + TWAINDIRECTMETADATA = 0x124B, + IAFIELDA_VALUE = 0x124C, + IAFIELDB_VALUE = 0x124D, + IAFIELDC_VALUE = 0x124E, + IAFIELDD_VALUE = 0x124F, + IAFIELDE_VALUE = 0x1250, + IALEVEL = 0x1251, + PRINTER = 0x1252, + BARCODETEXT2 = 0x1253, +} + +public enum TWEJ : ushort +{ + NONE = 0x0000, + MIDSEPARATOR = 0x0001, + PATCH1 = 0x0002, + PATCH2 = 0x0003, + PATCH3 = 0x0004, + PATCH4 = 0x0005, + PATCH6 = 0x0006, + PATCHT = 0x0007 +} + +#endregion + + +/////////////////////////////////////////////////////////////////////////////// +// Return Codes and Condition Codes section... +/////////////////////////////////////////////////////////////////////////////// +#region Return Codes and Condition Codes section... + +//public enum STS +//{ +// // Custom base (same for TWRC and TWCC)... +// CUSTOMBASE = 0x8000, + +// // Return codes... +// SUCCESS = 0, +// FAILURE = 1, +// CHECKSTATUS = 2, +// CANCEL = 3, +// DSEVENT = 4, +// NOTDSEVENT = 5, +// XFERDONE = 6, +// ENDOFLIST = 7, +// INFONOTSUPPORTED = 8, +// DATANOTAVAILABLE = 9, +// BUSY = 10, +// SCANNERLOCKED = 11, + +// // Condition codes (always associated with TWRC_FAILURE)... +// BUMMER = TwainConst.STSCC + 1, +// LOWMEMORY = TwainConst.STSCC + 2, +// NODS = TwainConst.STSCC + 3, +// MAXCONNECTIONS = TwainConst.STSCC + 4, +// OPERATIONERROR = TwainConst.STSCC + 5, +// BADCAP = TwainConst.STSCC + 6, +// BADPROTOCOL = TwainConst.STSCC + 9, +// BADVALUE = TwainConst.STSCC + 10, +// SEQERROR = TwainConst.STSCC + 11, +// BADDEST = TwainConst.STSCC + 12, +// CAPUNSUPPORTED = TwainConst.STSCC + 13, +// CAPBADOPERATION = TwainConst.STSCC + 14, +// CAPSEQERROR = TwainConst.STSCC + 15, +// DENIED = TwainConst.STSCC + 16, +// FILEEXISTS = TwainConst.STSCC + 17, +// FILENOTFOUND = TwainConst.STSCC + 18, +// NOTEMPTY = TwainConst.STSCC + 19, +// PAPERJAM = TwainConst.STSCC + 20, +// PAPERDOUBLEFEED = TwainConst.STSCC + 21, +// FILEWRITEERROR = TwainConst.STSCC + 22, +// CHECKDEVICEONLINE = TwainConst.STSCC + 23, +// INTERLOCK = TwainConst.STSCC + 24, +// DAMAGEDCORNER = TwainConst.STSCC + 25, +// FOCUSERROR = TwainConst.STSCC + 26, +// DOCTOOLIGHT = TwainConst.STSCC + 27, +// DOCTOODARK = TwainConst.STSCC + 28, +// NOMEDIA = TwainConst.STSCC + 29 +//} + +/// +/// bit patterns: for query the operation that are supported by the data source on a capability +/// Application gets these through DG_CONTROL/DAT_CAPABILITY/MSG_QUERYSUPPORT +/// +[Flags] +public enum TWQC : ushort +{ + Unknown = 0, + GET = 0x0001, + SET = 0x0002, + GETDEFAULT = 0x0004, + GETCURRENT = 0x0008, + RESET = 0x0010, + SETCONSTRAINT = 0x0020, + CONSTRAINABLE = 0x0040, + // KODAK additions + /// + /// KODAK ONLY: applies to entire session/machine + /// + MACHINE = 0x1000, + /// + /// KODAK ONLY: applies to Bitonal "cameras" + /// + BITONAL = 0x2000, + /// + /// KODAK ONLY: applies to Color "cameras" + /// + COLOR = 0x3000 +} + +/// +/// The TWAIN States... +/// +public enum STATE +{ + S1 = 1, // Nothing loaded or open + S2 = 2, // DSM loaded + S3 = 3, // DSM open + S4 = 4, // Data Source open, programmatic mode (no GUI) + S5 = 5, // GUI up or waiting to transfer first image + S6 = 6, // ready to start transferring image + S7 = 7 // transferring image or transfer done +} + +#endregion + + +/////////////////////////////////////////////////////////////////////////////// +// Language section... +/////////////////////////////////////////////////////////////////////////////// +#region Language section... + +/// +/// Handle encoding between C# and what the DS is currently set to. +/// NOTE: this is static for users of this object do not have to track +/// the encoding (i.e. let cs deal with all of this). This +/// means there is one language for all open DSes, so the last one wins. +/// +public static class Language +{ + /// + /// The encoding to use for strings to/from the DS + /// + /// + public static Encoding GetEncoding() + { + return (m_encoding); + } + + /// + /// The current language of the DS + /// + /// + public static void Set(TWLG a_twlg) + { + switch (a_twlg) + { + default: + // NOTE: can only get here if a TWLG was added, but it wasn't added here + m_encoding = Encoding.GetEncoding(1252); + break; + + case TWLG.USERLOCALE: + // NOTE: this should never come back from the DS. only here for completeness + m_encoding = Encoding.GetEncoding(1252); + break; + + case TWLG.THAI: + m_encoding = Encoding.GetEncoding(874); + break; + + case TWLG.JAPANESE: + m_encoding = Encoding.GetEncoding(932); + break; + + case TWLG.CHINESE: + case TWLG.CHINESE_PRC: + case TWLG.CHINESE_SINGAPORE: + case TWLG.CHINESE_SIMPLIFIED: + m_encoding = Encoding.GetEncoding(936); + break; + + case TWLG.KOREAN: + case TWLG.KOREAN_JOHAB: + m_encoding = Encoding.GetEncoding(949); + break; + + case TWLG.CHINESE_HONGKONG: + case TWLG.CHINESE_TAIWAN: + case TWLG.CHINESE_TRADITIONAL: + m_encoding = Encoding.GetEncoding(950); + break; + + case TWLG.ALBANIA: + case TWLG.CROATIA: + case TWLG.CZECH: + case TWLG.HUNGARIAN: + case TWLG.POLISH: + case TWLG.ROMANIAN: + case TWLG.SERBIAN_LATIN: + case TWLG.SLOVAK: + case TWLG.SLOVENIAN: + m_encoding = Encoding.GetEncoding(1250); + break; + + case TWLG.BYELORUSSIAN: + case TWLG.BULGARIAN: + case TWLG.RUSSIAN: + case TWLG.SERBIAN_CYRILLIC: + case TWLG.UKRANIAN: + m_encoding = Encoding.GetEncoding(1251); + break; + + case TWLG.AFRIKAANS: + case TWLG.BASQUE: + case TWLG.CATALAN: + case TWLG.DAN: // DANISH + case TWLG.DUT: // DUTCH + case TWLG.DUTCH_BELGIAN: + case TWLG.ENG: // ENGLISH + case TWLG.ENGLISH_AUSTRALIAN: + case TWLG.ENGLISH_CANADIAN: + case TWLG.ENGLISH_IRELAND: + case TWLG.ENGLISH_NEWZEALAND: + case TWLG.ENGLISH_SOUTHAFRICA: + case TWLG.ENGLISH_UK: + case TWLG.USA: + case TWLG.FAEROESE: + case TWLG.FIN: // FINNISH + case TWLG.FRN: // FRENCH + case TWLG.FRENCH_BELGIAN: + case TWLG.FCF: // FRENCH_CANADIAN + case TWLG.FRENCH_LUXEMBOURG: + case TWLG.FRENCH_SWISS: + case TWLG.GER: // GERMAN + case TWLG.GERMAN_AUSTRIAN: + case TWLG.GERMAN_LIECHTENSTEIN: + case TWLG.GERMAN_LUXEMBOURG: + case TWLG.GERMAN_SWISS: + case TWLG.ICE: // ICELANDIC + case TWLG.INDONESIAN: + case TWLG.ITN: // ITALIAN + case TWLG.ITALIAN_SWISS: + case TWLG.NOR: // NORWEGIAN + case TWLG.NORWEGIAN_BOKMAL: + case TWLG.NORWEGIAN_NYNORSK: + case TWLG.POR: // PORTUGUESE + case TWLG.PORTUGUESE_BRAZIL: + case TWLG.SPA: // SPANISH + case TWLG.SPANISH_MEXICAN: + case TWLG.SPANISH_MODERN: + case TWLG.SWE: // SWEDISH + case TWLG.SWEDISH_FINLAND: + m_encoding = Encoding.GetEncoding(1252); + break; + + case TWLG.GREEK: + m_encoding = Encoding.GetEncoding(1253); + break; + + case TWLG.TURKISH: + m_encoding = Encoding.GetEncoding(1254); + break; + + case TWLG.HEBREW: + m_encoding = Encoding.GetEncoding(1255); + break; + + case TWLG.ARABIC: + case TWLG.ARABIC_ALGERIA: + case TWLG.ARABIC_BAHRAIN: + case TWLG.ARABIC_EGYPT: + case TWLG.ARABIC_IRAQ: + case TWLG.ARABIC_JORDAN: + case TWLG.ARABIC_KUWAIT: + case TWLG.ARABIC_LEBANON: + case TWLG.ARABIC_LIBYA: + case TWLG.ARABIC_MOROCCO: + case TWLG.ARABIC_OMAN: + case TWLG.ARABIC_QATAR: + case TWLG.ARABIC_SAUDIARABIA: + case TWLG.ARABIC_SYRIA: + case TWLG.ARABIC_TUNISIA: + case TWLG.ARABIC_UAE: + case TWLG.ARABIC_YEMEN: + case TWLG.FARSI: + case TWLG.URDU: + m_encoding = Encoding.GetEncoding(1256); + break; + + case TWLG.ESTONIAN: + case TWLG.LATVIAN: + case TWLG.LITHUANIAN: + m_encoding = Encoding.GetEncoding(1257); + break; + + case TWLG.VIETNAMESE: + m_encoding = Encoding.GetEncoding(1258); + break; + + case TWLG.ASSAMESE: + case TWLG.BENGALI: + case TWLG.BIHARI: + case TWLG.BODO: + case TWLG.DOGRI: + case TWLG.GUJARATI: + case TWLG.HARYANVI: + case TWLG.HINDI: + case TWLG.KANNADA: + case TWLG.KASHMIRI: + case TWLG.MALAYALAM: + case TWLG.MARATHI: + case TWLG.MARWARI: + case TWLG.MEGHALAYAN: + case TWLG.MIZO: + case TWLG.NAGA: + case TWLG.ORISSI: + case TWLG.PUNJABI: + case TWLG.PUSHTU: + case TWLG.SIKKIMI: + case TWLG.TAMIL: + case TWLG.TELUGU: + case TWLG.TRIPURI: + // NOTE: there are no known code pages for these, so we will use English + m_encoding = Encoding.GetEncoding(1252); + break; + } + } + + private static Encoding m_encoding = Encoding.GetEncoding(1252); +} + +#endregion diff --git a/src/NTwain/Data/TWAINH_EXTRAS.cs b/src/NTwain/Data/TWAINH_EXTRAS.cs index f449900..982637e 100644 --- a/src/NTwain/Data/TWAINH_EXTRAS.cs +++ b/src/NTwain/Data/TWAINH_EXTRAS.cs @@ -1,710 +1,735 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; -using System.Linq; using System.Runtime.InteropServices; using System.Text; -namespace NTwain.Data +namespace NTwain.Data; + +// this contains my additions +// that makes some twain types easier to work with. + +/// +/// Contains platform info for twain use. +/// +public static class TWPlatform { - // this contains my additions - // that makes some twain types easier to work with. - - /// - /// Contains platform info for twain use. - /// - public static class TWPlatform + static TWPlatform() { - static TWPlatform() - { - Is32bit = IntPtr.Size == 4; - + Is32bit = IntPtr.Size == 4; #if NETFRAMEWORK - if (Environment.OSVersion.Platform == PlatformID.Win32NT) - { - IsWindows = true; - } - else if (System.IO.Directory.Exists("/Library/Application Support")) - { - IsMacOSX = true; - } - else if (Environment.OSVersion.Platform == PlatformID.Unix) - { - IsLinux = true; - } + if (Environment.OSVersion.Platform == PlatformID.Win32NT) + { + IsWindows = true; + } + else if (System.IO.Directory.Exists("/Library/Application Support")) + { + IsMacOSX = true; + } + else if (Environment.OSVersion.Platform == PlatformID.Unix) + { + IsLinux = true; + } #else - Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - IsWindows = true; - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - IsMacOSX = true; - } - else - { - IsLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); - } + if (OperatingSystem.IsWindows()) + { + IsWindows = true; + } + else if (OperatingSystem.IsMacCatalyst() || OperatingSystem.IsMacOS()) + { + IsMacOSX = true; + } + else + { + IsLinux = OperatingSystem.IsLinux(); + } +#endif +#if !NETFRAMEWORK + Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); #endif - } - - /// - /// Whether the code is running under Linux. - /// - public static bool IsLinux { get; } - - /// - /// Whether the code is running under MacOSX. - /// - public static bool IsMacOSX { get; } - - /// - /// Whether the code is running under Windows. - /// - public static bool IsWindows { get; } - - /// - /// Whether the code is running in 64bit or 32bit. - /// - public static bool Is32bit { get; } - - /// - /// Whether to use the older DSM lib on Windows and Mac. - /// On Windows it only takes effect when running in 32bit. - /// Defaults to false. - /// - public static bool PreferLegacyDSM { get; set; } } /// - /// Contains value that don't fit into enums nicely. + /// Whether the code is running under Linux. /// - public static class TWConst - { - /// - /// Don't care values... - /// - public const byte TWON_DONTCARE8 = 0xff; - public const ushort TWON_DONTCARE16 = 0xffff; - public const uint TWON_DONTCARE32 = 0xffffffff; - } + public static bool IsLinux { get; } /// - /// TWAIN's boolean values. + /// Whether the code is running under MacOSX. /// - public enum TW_BOOL : ushort - { - /// - /// The false value (0). - /// - False = 0, - /// - /// The true value (1). - /// - True = 1 - } - - ///// - ///// A more dotnet-friendly representation of . - ///// - //public struct Metrics - //{ - // /// - // /// Return code of querying the metrics. - // /// - // public STS ReturnCode; - - // /// - // /// The number of sheets of paper processed by the scanner. - // /// - // public int Sheets; - - // /// - // /// The number of images made available for transfer by the driver. This is not - // /// necessarily the same as the number of images actually transferred, since the - // /// application may opt to skip transfers or to end without transferring all images. - // /// - // public int Images; - //} + public static bool IsMacOSX { get; } /// - /// More dotnet friendly return type for twaindirect set result. + /// Whether the code is running under Windows. /// - public struct TwainDirectTaskResult - { - /// - /// Return code of task. - /// - public TWRC ReturnCode; - - /// - /// Status if code is failure. - /// - public TW_STATUS Status; - - /// - /// The response of the task in JSON if successful. - /// - public string? ResponseJson; - } - - public enum TWRC : ushort - { - // Custom base (same for TWRC and TWCC)... - CUSTOMBASE = 0x8000, - - // Return codes... - SUCCESS = 0, - FAILURE = 1, - CHECKSTATUS = 2, - CANCEL = 3, - DSEVENT = 4, - NOTDSEVENT = 5, - XFERDONE = 6, - ENDOFLIST = 7, - INFONOTSUPPORTED = 8, - DATANOTAVAILABLE = 9, - BUSY = 10, - SCANNERLOCKED = 11, - } - public enum TWCC : ushort - { - // Condition codes (always associated with TWRC_FAILURE)... - CUSTOMBASE = 0x8000, - None = 0, - BUMMER = 1, - LOWMEMORY = 2, - NODS = 3, - MAXCONNECTIONS = 4, - OPERATIONERROR = 5, - BADCAP = 6, - BADPROTOCOL = 9, - BADVALUE = 10, - SEQERROR = 11, - BADDEST = 12, - CAPUNSUPPORTED = 13, - CAPBADOPERATION = 14, - CAPSEQERROR = 15, - DENIED = 16, - FILEEXISTS = 17, - FILENOTFOUND = 18, - NOTEMPTY = 19, - PAPERJAM = 20, - PAPERDOUBLEFEED = 21, - FILEWRITEERROR = 22, - CHECKDEVICEONLINE = 23, - INTERLOCK = 24, - DAMAGEDCORNER = 25, - FOCUSERROR = 26, - DOCTOOLIGHT = 27, - DOCTOODARK = 28, - NOMEDIA = 29 - } - - //[StructLayout(LayoutKind.Sequential, Pack = 2)] + public static bool IsWindows { get; } /// - /// Extended return type with original return code and additional - /// status if RC is . + /// Whether the code is running in 64bit or 32bit. /// - public struct STS - { - /// - /// The original return code. - /// - public TWRC RC; - - /// - /// Additional status if RC is . - /// - public TW_STATUS STATUS; - - ///// - ///// For easy conversion from DSM calls to the one we want - ///// - ///// - //public static implicit operator STS(TWRC rc) - //{ - // return new STS { RC = rc }; - //} - - /// - /// Quick check if the RC is success. - /// - public bool IsSuccess => RC == TWRC.SUCCESS; - - /// - /// Quick access to condition code. - /// - public TWCC ConditionCode => STATUS.ConditionCode; - - public override string ToString() - { - return $"{RC} - {STATUS.ConditionCode}"; - } - } - - partial struct TW_STATUS - { - public override string ToString() - { - return ConditionCode.ToString(); - } - } + public static bool Is32bit { get; } /// - /// A more dotnet-friendly representation of . + /// Whether to use the older DSM lib on Windows and Mac. + /// On Windows it only takes effect when running in 32bit. + /// Defaults to false. /// - /// - public record Enumeration - { - public int CurrentIndex { get; set; } + public static bool PreferLegacyDSM { get; set; } +} - public int DefaultIndex { get; set; } +/// +/// Contains value that don't fit into enums nicely. +/// +public static class TWConst +{ + /// + /// Don't care values... + /// + public const byte TWON_DONTCARE8 = 0xff; + public const ushort TWON_DONTCARE16 = 0xffff; + public const uint TWON_DONTCARE32 = 0xffffffff; +} - public TValue[] Items { get; set; } = []; - } +/// +/// TWAIN's boolean values. +/// +public enum TW_BOOL : ushort +{ + /// + /// The false value (0). + /// + False = 0, + /// + /// The true value (1). + /// + True = 1 +} + +///// +///// A more dotnet-friendly representation of . +///// +//public struct Metrics +//{ +// /// +// /// Return code of querying the metrics. +// /// +// public STS ReturnCode; + +// /// +// /// The number of sheets of paper processed by the scanner. +// /// +// public int Sheets; + +// /// +// /// The number of images made available for transfer by the driver. This is not +// /// necessarily the same as the number of images actually transferred, since the +// /// application may opt to skip transfers or to end without transferring all images. +// /// +// public int Images; +//} + +/// +/// More dotnet friendly return type for twaindirect set result. +/// +public struct TwainDirectTaskResult +{ + /// + /// Return code of task. + /// + public TWRC ReturnCode; /// - /// A more dotnet-friendly representation of . + /// Status if code is failure. /// - /// - public partial record Range - { - public required TValue MinValue { get; set; } - public required TValue MaxValue { get; set; } - public required TValue StepSize { get; set; } - public required TValue DefaultValue { get; set; } - public required TValue CurrentValue { get; set; } - - /// - /// Tries to enumerate the range values. - /// This could be expensive depending on the range size. - /// - /// - public IEnumerable Enumerate() - { - if (MinValue is not IConvertible) - throw new NotSupportedException($"The value type {typeof(TValue).Name} is not supported for range enumeration."); - - var dynamicType = typeof(DynamicEnumerator<>); - var genericType = dynamicType.MakeGenericType(typeof(TValue)); - - var de = (IEnumerator)Activator.CreateInstance(genericType, MinValue, MaxValue, StepSize)!; - while (de.MoveNext()) - { - yield return de.Current; - } - } - } + public TW_STATUS Status; /// - /// A more dotnet-friendly container of CAP value. + /// The response of the task in JSON if successful. /// - /// - public record ValueContainer + public string? ResponseJson; +} + +public enum TWRC : ushort +{ + // Custom base (same for TWRC and TWCC)... + CUSTOMBASE = 0x8000, + + // Return codes... + SUCCESS = 0, + FAILURE = 1, + CHECKSTATUS = 2, + CANCEL = 3, + DSEVENT = 4, + NOTDSEVENT = 5, + XFERDONE = 6, + ENDOFLIST = 7, + INFONOTSUPPORTED = 8, + DATANOTAVAILABLE = 9, + BUSY = 10, + SCANNERLOCKED = 11, +} +public enum TWCC : ushort +{ + // Condition codes (always associated with TWRC_FAILURE)... + CUSTOMBASE = 0x8000, + None = 0, + BUMMER = 1, + LOWMEMORY = 2, + NODS = 3, + MAXCONNECTIONS = 4, + OPERATIONERROR = 5, + BADCAP = 6, + BADPROTOCOL = 9, + BADVALUE = 10, + SEQERROR = 11, + BADDEST = 12, + CAPUNSUPPORTED = 13, + CAPBADOPERATION = 14, + CAPSEQERROR = 15, + DENIED = 16, + FILEEXISTS = 17, + FILENOTFOUND = 18, + NOTEMPTY = 19, + PAPERJAM = 20, + PAPERDOUBLEFEED = 21, + FILEWRITEERROR = 22, + CHECKDEVICEONLINE = 23, + INTERLOCK = 24, + DAMAGEDCORNER = 25, + FOCUSERROR = 26, + DOCTOOLIGHT = 27, + DOCTOODARK = 28, + NOMEDIA = 29 +} + +//[StructLayout(LayoutKind.Sequential, Pack = 2)] + +/// +/// Extended return type with original return code and additional +/// status if RC is . +/// +public struct STS +{ + /// + /// Returns a failure with sequence error condition. + /// + /// + public static STS SequenceError() { - public TWON ContainerType { get; set; } - - public TValue? OneValue { get; set; } - - public IList? ArrayValue { get; set; } - - public Enumeration? EnumValue { get; set; } - - public Range? RangeValue { get; set; } - - public IEnumerable GetValues() + return new STS { - return ContainerType switch + RC = TWRC.FAILURE, + STATUS = new TW_STATUS { - TWON.ONEVALUE => ToEnumerable(OneValue), - TWON.ARRAY => ArrayValue ?? [], - TWON.ENUMERATION => EnumValue?.Items ?? [], - TWON.RANGE => RangeValue != null ? RangeValue.Enumerate() : [], - _ => [], - }; - } - - private IEnumerable ToEnumerable(TValue? value) - { - if (value == null) yield break; - yield return value; - } - } - - partial struct TW_FIX32 : IEquatable, IConvertible - { - // this conversion logic is found in the twain spec. - - float ToFloat() - { - return Whole + Frac / 65536f; - } - double ToDouble() - { - return Whole + Frac / 65536.0; - } - public TW_FIX32(double value) : this((float)value) { } - public TW_FIX32(float value) - { - //int temp = (int)(value * 65536.0 + 0.5); - //Whole = (short)(temp >> 16); - //Fraction = (ushort)(temp & 0x0000ffff); - - // different version from twain faq - bool sign = value < 0; - int temp = (int)(value * 65536.0 + (sign ? (-0.5) : 0.5)); - Whole = (short)(temp >> 16); - Frac = (ushort)(temp & 0x0000ffff); - } - - public override string ToString() - { - return ToFloat().ToString(); - } - - public bool Equals(TW_FIX32 other) - { - return Whole == other.Whole && Frac == other.Frac; - } - public override bool Equals(object? obj) - { - if (obj is TW_FIX32 other) - { - return Equals(other); - } - return false; - } - public override int GetHashCode() - { - return Whole ^ Frac; - } - - - #region IConvertable - - TypeCode IConvertible.GetTypeCode() - { - return TypeCode.Single; - } - - bool IConvertible.ToBoolean(IFormatProvider? provider) - { - return this != 0; - } - - byte IConvertible.ToByte(IFormatProvider? provider) - { - return Convert.ToByte((float)this); - } - - char IConvertible.ToChar(IFormatProvider? provider) - { - return Convert.ToChar((float)this); - } - - DateTime IConvertible.ToDateTime(IFormatProvider? provider) - { - return Convert.ToDateTime((float)this); - } - - decimal IConvertible.ToDecimal(IFormatProvider? provider) - { - return Convert.ToDecimal((float)this); - } - - double IConvertible.ToDouble(IFormatProvider? provider) - { - return Convert.ToDouble((float)this); - } - - short IConvertible.ToInt16(IFormatProvider? provider) - { - return Convert.ToInt16((float)this); - } - - int IConvertible.ToInt32(IFormatProvider? provider) - { - return Convert.ToInt32((float)this); - } - - long IConvertible.ToInt64(IFormatProvider? provider) - { - return Convert.ToInt64((float)this); - } - - sbyte IConvertible.ToSByte(IFormatProvider? provider) - { - return Convert.ToSByte((float)this); - } - - float IConvertible.ToSingle(IFormatProvider? provider) - { - return Convert.ToSingle((float)this); - } - - string IConvertible.ToString(IFormatProvider? provider) - { - return this.ToString(); - } - - object IConvertible.ToType(Type conversionType, IFormatProvider? provider) - { - return Convert.ChangeType((float)this, conversionType, CultureInfo.InvariantCulture); - } - - ushort IConvertible.ToUInt16(IFormatProvider? provider) - { - return Convert.ToUInt16((float)this); - } - - uint IConvertible.ToUInt32(IFormatProvider? provider) - { - return Convert.ToUInt32((float)this); - } - - ulong IConvertible.ToUInt64(IFormatProvider? provider) - { - return Convert.ToUInt64((float)this); - } - - #endregion - - public static implicit operator float(TW_FIX32 value) => value.ToFloat(); - public static implicit operator TW_FIX32(float value) => new(value); - - public static implicit operator double(TW_FIX32 value) => value.ToDouble(); - public static implicit operator TW_FIX32(double value) => new(value); - - public static bool operator ==(TW_FIX32 value1, TW_FIX32 value2) => value1.Equals(value2); - public static bool operator !=(TW_FIX32 value1, TW_FIX32 value2) => !value1.Equals(value2); - } - - partial struct TW_FRAME : IEquatable - { - /// - /// Creates from a string representation of it. - /// - /// - public TW_FRAME(string value) : this() - { - var parts = value.Split(','); - if (parts.Length == 4) - { - Left = float.Parse(parts[0]); - Top = float.Parse(parts[1]); - Right = float.Parse(parts[2]); - Bottom = float.Parse(parts[3]); - } - else - { - throw new ArgumentException($"Cannot create frame from \"{value}\"."); - } - } - - /// - /// String representation of Left,Top,Right,Bottom. - /// - /// - public override string ToString() - { - return $"({Left},{Top}) ({Right},{Bottom})"; - } - - public bool Equals(TW_FRAME other) - { - return Left == other.Left && Top == other.Top && - Right == other.Right && Bottom == other.Bottom; - } - - public override bool Equals(object? obj) - { - if (obj is TW_FRAME other) - { - return Equals(other); - } - return false; - } - - public override int GetHashCode() - { - return Left.GetHashCode() ^ Top.GetHashCode() ^ - Right.GetHashCode() ^ Bottom.GetHashCode(); - } - - - public static bool operator ==(TW_FRAME value1, TW_FRAME value2) - { - return value1.Equals(value2); - } - public static bool operator !=(TW_FRAME value1, TW_FRAME value2) - { - return !value1.Equals(value2); - } - } - - partial struct TW_STR32 - { - public const int Size = 34; - - public TW_STR32(string value) : this() - { - Set(value); - } - - public override string ToString() - { - return Get(); - } - - public static implicit operator string(TW_STR32 value) => value.ToString(); - public static implicit operator TW_STR32(string value) => new(value); - - } - - partial struct TW_STR64 - { - public const int Size = 66; - - public TW_STR64(string value) : this() - { - Set(value); - } - - public override string ToString() - { - return Get(); - } - - public static implicit operator string(TW_STR64 value) => value.ToString(); - public static implicit operator TW_STR64(string value) => new(value); - } - - partial struct TW_STR128 - { - public const int Size = 130; - - public TW_STR128(string value) : this() - { - Set(value); - } - - public override string ToString() - { - return Get(); - } - - public static implicit operator string(TW_STR128 value) => value.ToString(); - public static implicit operator TW_STR128(string value) => new(value); - } - - partial struct TW_STR255 - { - public const int Size = 256; - - public TW_STR255(string value) : this() - { - Set(value); - } - - public override string ToString() - { - return Get(); - } - - public static implicit operator string(TW_STR255 value) => value.ToString(); - public static implicit operator TW_STR255(string value) => new(value); - } - - partial struct TW_IDENTITY - { - public override string ToString() - { - return $"{Manufacturer} - {ProductFamily} - {ProductName} {Version} (TWAIN {ProtocolMajor}.{ProtocolMinor})"; - } - } - partial struct TW_IDENTITY_MACOSX - { - public override string ToString() - { - return $"{Manufacturer} - {ProductName} v{Version.MajorNum}.{Version.MinorNum} (TWAIN {ProtocolMajor}.{ProtocolMinor})"; - } - public static implicit operator TW_IDENTITY_LEGACY(TW_IDENTITY_MACOSX value) => new() - { - Id = value.Id, - Manufacturer = value.Manufacturer, - ProductFamily = value.ProductFamily, - ProductName = value.ProductName, - ProtocolMajor = value.ProtocolMajor, - ProtocolMinor = value.ProtocolMinor, - SupportedGroups = value.SupportedGroups, - Version = new() - { - Country = value.Version.Country, - Info = value.Version.Info, - Language = value.Version.Language, - MajorNum = value.Version.MajorNum, - MinorNum = value.Version.MinorNum, + ConditionCode = TWCC.SEQERROR } }; } - partial struct TW_IDENTITY_LEGACY + + /// + /// The original return code. + /// + public TWRC RC; + + /// + /// Additional status if RC is . + /// + public TW_STATUS STATUS; + + ///// + ///// For easy conversion from DSM calls to the one we want + ///// + ///// + //public static implicit operator STS(TWRC rc) + //{ + // return new STS { RC = rc }; + //} + + /// + /// Quick check if the RC is success. + /// + public bool IsSuccess => RC == TWRC.SUCCESS; + + /// + /// Quick access to condition code. + /// + public TWCC ConditionCode => STATUS.ConditionCode; + + public override string ToString() { - /// - /// Creates app info derived an executable file. - /// - /// - /// - /// - public TW_IDENTITY_LEGACY( - string exeFilePath, - TWLG appLanguage = TWLG.ENGLISH_USA, TWCY appCountry = TWCY.USA) : - this(FileVersionInfo.GetVersionInfo(exeFilePath), appLanguage, appCountry) - { } - /// - /// Creates app info derived from a object. - /// - /// - /// - /// - public TW_IDENTITY_LEGACY( - FileVersionInfo appInfo, - TWLG appLanguage = TWLG.ENGLISH_USA, TWCY appCountry = TWCY.USA) : - this( - appInfo.CompanyName ?? "", - appInfo.ProductName ?? "", - appInfo.ProductName ?? "", - new Version(appInfo.FileVersion ?? "1.0"), - appInfo.FileDescription ?? "", appLanguage, appCountry) - { } - /// - /// Creates id with explicit app info. - /// - /// - /// - /// - /// - /// - /// - /// - /// - public TW_IDENTITY_LEGACY( - string companyName, string productFamily, string productName, - Version productVersion, string productDescription = "", - TWLG appLanguage = TWLG.ENGLISH_USA, TWCY appCountry = TWCY.USA, - DG supportedTypes = DG.IMAGE) + return $"{RC} - {STATUS.ConditionCode}"; + } +} + +partial struct TW_STATUS +{ + public override string ToString() + { + return ConditionCode.ToString(); + } +} + +/// +/// A more dotnet-friendly representation of . +/// +/// +public record Enumeration +{ + public int CurrentIndex { get; set; } + + public int DefaultIndex { get; set; } + + public TValue[] Items { get; set; } = []; +} + +/// +/// A more dotnet-friendly representation of . +/// +/// +public partial record Range +{ + public required TValue MinValue { get; set; } + public required TValue MaxValue { get; set; } + public required TValue StepSize { get; set; } + public required TValue DefaultValue { get; set; } + public required TValue CurrentValue { get; set; } + + /// + /// Tries to enumerate the range values. + /// This could be expensive depending on the range size. + /// + /// + public IEnumerable Enumerate() + { + if (MinValue is not IConvertible) + throw new NotSupportedException($"The value type {typeof(TValue).Name} is not supported for range enumeration."); + + var dynamicType = typeof(DynamicEnumerator<>); + var genericType = dynamicType.MakeGenericType(typeof(TValue)); + + var de = (IEnumerator)Activator.CreateInstance(genericType, MinValue, MaxValue, StepSize)!; + while (de.MoveNext()) { - Manufacturer = companyName; - ProductFamily = productFamily; - ProductName = productName; - ProtocolMajor = (ushort)TWON_PROTOCOL.MAJOR; - ProtocolMinor = (ushort)TWON_PROTOCOL.MINOR; - SupportedGroups = (uint)(supportedTypes | DG.CONTROL | DG.APP2); + yield return de.Current; + } + } +} + +/// +/// A more dotnet-friendly container of CAP value. +/// +/// +public record ValueContainer +{ + public TWON ContainerType { get; set; } + + public TValue? OneValue { get; set; } + + public IList? ArrayValue { get; set; } + + public Enumeration? EnumValue { get; set; } + + public Range? RangeValue { get; set; } + + public IEnumerable GetValues() + { + return ContainerType switch + { + TWON.ONEVALUE => ToEnumerable(OneValue), + TWON.ARRAY => ArrayValue ?? [], + TWON.ENUMERATION => EnumValue?.Items ?? [], + TWON.RANGE => RangeValue != null ? RangeValue.Enumerate() : [], + _ => [], + }; + } + + private IEnumerable ToEnumerable(TValue? value) + { + if (value == null) yield break; + yield return value; + } +} + + +partial struct TW_ENTRYPOINT_DELEGATES +{ + public bool HasDelegates() + { + return DSM_MemAllocate != null && + DSM_MemFree != null && + DSM_MemLock != null && + DSM_MemUnlock != null; + } +} + +partial struct TW_FIX32 : IEquatable, IConvertible +{ + // this conversion logic is found in the twain spec. + + float ToFloat() + { + return Whole + Frac / 65536f; + } + double ToDouble() + { + return Whole + Frac / 65536.0; + } + public TW_FIX32(double value) : this((float)value) { } + public TW_FIX32(float value) + { + //int temp = (int)(value * 65536.0 + 0.5); + //Whole = (short)(temp >> 16); + //Fraction = (ushort)(temp & 0x0000ffff); + + // different version from twain faq + bool sign = value < 0; + int temp = (int)(value * 65536.0 + (sign ? (-0.5) : 0.5)); + Whole = (short)(temp >> 16); + Frac = (ushort)(temp & 0x0000ffff); + } + + public override string ToString() + { + return ToFloat().ToString(); + } + + public bool Equals(TW_FIX32 other) + { + return Whole == other.Whole && Frac == other.Frac; + } + public override bool Equals(object? obj) + { + if (obj is TW_FIX32 other) + { + return Equals(other); + } + return false; + } + public override int GetHashCode() + { + return Whole ^ Frac; + } + + + #region IConvertable + + TypeCode IConvertible.GetTypeCode() + { + return TypeCode.Single; + } + + bool IConvertible.ToBoolean(IFormatProvider? provider) + { + return this != 0; + } + + byte IConvertible.ToByte(IFormatProvider? provider) + { + return Convert.ToByte((float)this); + } + + char IConvertible.ToChar(IFormatProvider? provider) + { + return Convert.ToChar((float)this); + } + + DateTime IConvertible.ToDateTime(IFormatProvider? provider) + { + return Convert.ToDateTime((float)this); + } + + decimal IConvertible.ToDecimal(IFormatProvider? provider) + { + return Convert.ToDecimal((float)this); + } + + double IConvertible.ToDouble(IFormatProvider? provider) + { + return Convert.ToDouble((float)this); + } + + short IConvertible.ToInt16(IFormatProvider? provider) + { + return Convert.ToInt16((float)this); + } + + int IConvertible.ToInt32(IFormatProvider? provider) + { + return Convert.ToInt32((float)this); + } + + long IConvertible.ToInt64(IFormatProvider? provider) + { + return Convert.ToInt64((float)this); + } + + sbyte IConvertible.ToSByte(IFormatProvider? provider) + { + return Convert.ToSByte((float)this); + } + + float IConvertible.ToSingle(IFormatProvider? provider) + { + return Convert.ToSingle((float)this); + } + + string IConvertible.ToString(IFormatProvider? provider) + { + return this.ToString(); + } + + object IConvertible.ToType(Type conversionType, IFormatProvider? provider) + { + return Convert.ChangeType((float)this, conversionType, CultureInfo.InvariantCulture); + } + + ushort IConvertible.ToUInt16(IFormatProvider? provider) + { + return Convert.ToUInt16((float)this); + } + + uint IConvertible.ToUInt32(IFormatProvider? provider) + { + return Convert.ToUInt32((float)this); + } + + ulong IConvertible.ToUInt64(IFormatProvider? provider) + { + return Convert.ToUInt64((float)this); + } + + #endregion + + public static implicit operator float(TW_FIX32 value) => value.ToFloat(); + public static implicit operator TW_FIX32(float value) => new(value); + + public static implicit operator double(TW_FIX32 value) => value.ToDouble(); + public static implicit operator TW_FIX32(double value) => new(value); + + public static bool operator ==(TW_FIX32 value1, TW_FIX32 value2) => value1.Equals(value2); + public static bool operator !=(TW_FIX32 value1, TW_FIX32 value2) => !value1.Equals(value2); +} + +partial struct TW_FRAME : IEquatable +{ + /// + /// Creates from a string representation of it. + /// + /// + public TW_FRAME(string value) : this() + { + var parts = value.Split(','); + if (parts.Length == 4) + { + Left = float.Parse(parts[0]); + Top = float.Parse(parts[1]); + Right = float.Parse(parts[2]); + Bottom = float.Parse(parts[3]); + } + else + { + throw new ArgumentException($"Cannot create frame from \"{value}\"."); + } + } + + /// + /// String representation of Left,Top,Right,Bottom. + /// + /// + public override string ToString() + { + return $"({Left},{Top}) ({Right},{Bottom})"; + } + + public bool Equals(TW_FRAME other) + { + return Left == other.Left && Top == other.Top && + Right == other.Right && Bottom == other.Bottom; + } + + public override bool Equals(object? obj) + { + if (obj is TW_FRAME other) + { + return Equals(other); + } + return false; + } + + public override int GetHashCode() + { + return Left.GetHashCode() ^ Top.GetHashCode() ^ + Right.GetHashCode() ^ Bottom.GetHashCode(); + } + + + public static bool operator ==(TW_FRAME value1, TW_FRAME value2) + { + return value1.Equals(value2); + } + public static bool operator !=(TW_FRAME value1, TW_FRAME value2) + { + return !value1.Equals(value2); + } +} + +partial struct TW_STR32 +{ + public const int Size = 34; + + public TW_STR32(string value) : this() + { + Set(value); + } + + public override string ToString() + { + return Get(); + } + + public static implicit operator string(TW_STR32 value) => value.ToString(); + public static implicit operator TW_STR32(string value) => new(value); + +} + +partial struct TW_STR64 +{ + public const int Size = 66; + + public TW_STR64(string value) : this() + { + Set(value); + } + + public override string ToString() + { + return Get(); + } + + public static implicit operator string(TW_STR64 value) => value.ToString(); + public static implicit operator TW_STR64(string value) => new(value); +} + +partial struct TW_STR128 +{ + public const int Size = 130; + + public TW_STR128(string value) : this() + { + Set(value); + } + + public override string ToString() + { + return Get(); + } + + public static implicit operator string(TW_STR128 value) => value.ToString(); + public static implicit operator TW_STR128(string value) => new(value); +} + +partial struct TW_STR255 +{ + public const int Size = 256; + + public TW_STR255(string value) : this() + { + Set(value); + } + + public override string ToString() + { + return Get(); + } + + public static implicit operator string(TW_STR255 value) => value.ToString(); + public static implicit operator TW_STR255(string value) => new(value); +} + +/// +/// A single wrapper type for various TW_IDENTITY types +/// to help pass it around. +/// +public record TWIdentityWrapper +{ + internal TW_IDENTITY TW_IDENTITY; + internal TW_IDENTITY_LEGACY TW_IDENTITY_LEGACY; + internal TW_IDENTITY_MACOSX TW_IDENTITY_MACOSX; + + public TWIdentityWrapper() + { + + } + + internal void SetIdentity(TW_IDENTITY_LEGACY identity) + { + TW_IDENTITY_LEGACY = identity; + TW_IDENTITY = identity; + TW_IDENTITY_MACOSX = identity; + } + internal void SetIdentity(TW_IDENTITY_MACOSX identity) + { + TW_IDENTITY_LEGACY = identity; + TW_IDENTITY = identity; + TW_IDENTITY_MACOSX = identity; + } + + /// + /// Creates app info derived an executable file. + /// + /// + /// + /// + public TWIdentityWrapper( + string exeFilePath, + TWLG appLanguage = TWLG.ENGLISH_USA, TWCY appCountry = TWCY.USA) : + this(FileVersionInfo.GetVersionInfo(exeFilePath), appLanguage, appCountry) + { } + + /// + /// Creates app info derived from a object. + /// + /// + /// + /// + public TWIdentityWrapper( + FileVersionInfo appInfo, + TWLG appLanguage = TWLG.ENGLISH_USA, TWCY appCountry = TWCY.USA) : + this( + appInfo.CompanyName ?? "", + appInfo.ProductName ?? "", + appInfo.ProductName ?? "", + new Version(appInfo.FileVersion ?? "1.0"), + appInfo.FileDescription ?? "", appLanguage, appCountry) + { } + + /// + /// Creates id with explicit app info. + /// + /// + /// + /// + /// + /// + /// + /// + /// + public TWIdentityWrapper( + string companyName, string productFamily, string productName, + Version productVersion, string productDescription = "", + TWLG appLanguage = TWLG.ENGLISH_USA, TWCY appCountry = TWCY.USA, + DG supportedTypes = DG.IMAGE) + { + SetIdentity(new TW_IDENTITY_LEGACY + { + Manufacturer = companyName, + ProductFamily = productFamily, + ProductName = productName, + ProtocolMajor = (ushort)TWON_PROTOCOL.MAJOR, + ProtocolMinor = (ushort)TWON_PROTOCOL.MINOR, + SupportedGroups = (uint)(supportedTypes | DG.CONTROL | DG.APP2), Version = new TW_VERSION { Country = appCountry, @@ -712,455 +737,561 @@ namespace NTwain.Data Language = appLanguage, MajorNum = (ushort)productVersion.Major, MinorNum = (ushort)productVersion.Minor, - }; - } - - - - /// - /// A simplified check on whether this has valid data from DSM. - /// - public bool HasValue => Id != 0 && ProtocolMajor != 0 && ProtocolMinor != 0; - - public override string ToString() - { - return $"{Manufacturer} - {ProductName} v{Version.MajorNum}.{Version.MinorNum} (TWAIN {ProtocolMajor}.{ProtocolMinor})"; - } - - public static implicit operator TW_IDENTITY(TW_IDENTITY_LEGACY value) => new() - { - Id = value.Id, - Manufacturer = value.Manufacturer, - ProductFamily = value.ProductFamily, - ProductName = value.ProductName, - ProtocolMajor = value.ProtocolMajor, - ProtocolMinor = value.ProtocolMinor, - SupportedGroups = value.SupportedGroups, - Version = new() - { - Country = value.Version.Country, - Info = value.Version.Info, - Language = value.Version.Language, - MajorNum = value.Version.MajorNum, - MinorNum = value.Version.MinorNum, } - }; - public static implicit operator TW_IDENTITY_MACOSX(TW_IDENTITY_LEGACY value) => new() - { - Id = value.Id, - Manufacturer = value.Manufacturer, - ProductFamily = value.ProductFamily, - ProductName = value.ProductName, - ProtocolMajor = value.ProtocolMajor, - ProtocolMinor = value.ProtocolMinor, - SupportedGroups = value.SupportedGroups, - Version = new() - { - Country = value.Version.Country, - Info = value.Version.Info, - Language = value.Version.Language, - MajorNum = value.Version.MajorNum, - MinorNum = value.Version.MinorNum, - } - }; + }); } - partial struct TW_VERSION + public uint Id => TW_IDENTITY_LEGACY.Id; + public TW_VERSION Version => TW_IDENTITY_LEGACY.Version; + public ushort ProtocolMajor => TW_IDENTITY_LEGACY.ProtocolMajor; + public ushort ProtocolMinor => TW_IDENTITY_LEGACY.ProtocolMinor; + public uint SupportedGroups => TW_IDENTITY_LEGACY.SupportedGroups; + public TW_STR32 Manufacturer => TW_IDENTITY_LEGACY.Manufacturer; + public TW_STR32 ProductFamily => TW_IDENTITY_LEGACY.ProductFamily; + public TW_STR32 ProductName => TW_IDENTITY_LEGACY.ProductName; + + public override string ToString() { - public override string ToString() - { - return $"{MajorNum}.{MinorNum}"; - } + return $"{Manufacturer} - {ProductFamily} - {ProductName} {Version} (TWAIN {ProtocolMajor}.{ProtocolMinor})"; + } + public static implicit operator TW_IDENTITY_LEGACY(TWIdentityWrapper wrapper) => wrapper.TW_IDENTITY_LEGACY; + public static implicit operator TW_IDENTITY_MACOSX(TWIdentityWrapper wrapper) => wrapper.TW_IDENTITY_MACOSX; + public static implicit operator TW_IDENTITY(TWIdentityWrapper wrapper) => wrapper.TW_IDENTITY; +} + +partial struct TW_IDENTITY +{ + public override string ToString() + { + return $"{Manufacturer} - {ProductFamily} - {ProductName} {Version} (TWAIN {ProtocolMajor}.{ProtocolMinor})"; } - partial struct TW_STATUSUTF8 + public static implicit operator TW_IDENTITY_LEGACY(TW_IDENTITY value) => new() { - /// - /// Frees the memory if necessary. - /// - /// - public void Free(IMemoryManager mgr) + Id = (uint)value.Id, + Manufacturer = value.Manufacturer, + ProductFamily = value.ProductFamily, + ProductName = value.ProductName, + ProtocolMajor = value.ProtocolMajor, + ProtocolMinor = value.ProtocolMinor, + SupportedGroups = value.SupportedGroups, + Version = new() { - // session already checks for zero - mgr.Free(UTF8string); - UTF8string = IntPtr.Zero; + Country = value.Version.Country, + Info = value.Version.Info, + Language = value.Version.Language, + MajorNum = value.Version.MajorNum, + MinorNum = value.Version.MinorNum, } - - /// - /// Tries to read the text content and optionally frees the memory. - /// - /// - /// Whether to free the pointer after reads. - /// - public string? Read(IMemoryManager mgr, bool freeMemory = true) + }; + public static implicit operator TW_IDENTITY_MACOSX(TW_IDENTITY value) => new() + { + Id = (uint)value.Id, + Manufacturer = value.Manufacturer, + ProductFamily = value.ProductFamily, + ProductName = value.ProductName, + ProtocolMajor = value.ProtocolMajor, + ProtocolMinor = value.ProtocolMinor, + SupportedGroups = value.SupportedGroups, + Version = new() { - string? val = null; - if (UTF8string != IntPtr.Zero && Size > 0) - { - val = UTF8string.PtrToStringUTF8(mgr, (int)Size); - } - if (freeMemory) Free(mgr); - return val; + Country = value.Version.Country, + Info = value.Version.Info, + Language = value.Version.Language, + MajorNum = value.Version.MajorNum, + MinorNum = value.Version.MinorNum, } + }; +} +partial struct TW_IDENTITY_MACOSX +{ + public override string ToString() + { + return $"{Manufacturer} - {ProductName} v{Version.MajorNum}.{Version.MinorNum} (TWAIN {ProtocolMajor}.{ProtocolMinor})"; } - partial struct TW_CAPABILITY + public static implicit operator TW_IDENTITY(TW_IDENTITY_MACOSX value) => new() { - public TW_CAPABILITY(CAP cap) + Id = value.Id, + Manufacturer = value.Manufacturer, + ProductFamily = value.ProductFamily, + ProductName = value.ProductName, + ProtocolMajor = value.ProtocolMajor, + ProtocolMinor = value.ProtocolMinor, + SupportedGroups = value.SupportedGroups, + Version = new() { - Cap = cap; - ConType = (TWON)TWConst.TWON_DONTCARE16; + Country = value.Version.Country, + Info = value.Version.Info, + Language = value.Version.Language, + MajorNum = value.Version.MajorNum, + MinorNum = value.Version.MinorNum, } + }; + public static implicit operator TW_IDENTITY_LEGACY(TW_IDENTITY_MACOSX value) => new() + { + Id = value.Id, + Manufacturer = value.Manufacturer, + ProductFamily = value.ProductFamily, + ProductName = value.ProductName, + ProtocolMajor = value.ProtocolMajor, + ProtocolMinor = value.ProtocolMinor, + SupportedGroups = value.SupportedGroups, + Version = new() + { + Country = value.Version.Country, + Info = value.Version.Info, + Language = value.Version.Language, + MajorNum = value.Version.MajorNum, + MinorNum = value.Version.MinorNum, + } + }; +} +partial struct TW_IDENTITY_LEGACY +{ + ///// + ///// A simplified check on whether this has valid data from DSM. + ///// + //public bool HasValue => Id != 0 && ProtocolMajor != 0 && ProtocolMinor != 0; - /// - /// Frees the memory if necessary. - /// - /// - public void Free(IMemoryManager mgr) - { - // session already checks for zero - mgr.Free(hContainer); - hContainer = IntPtr.Zero; - } + public override string ToString() + { + return $"{Manufacturer} - {ProductName} v{Version.MajorNum}.{Version.MinorNum} (TWAIN {ProtocolMajor}.{ProtocolMinor})"; } - partial struct TW_IMAGEINFO + public static implicit operator TW_IDENTITY(TW_IDENTITY_LEGACY value) => new() { - public override string ToString() + Id = value.Id, + Manufacturer = value.Manufacturer, + ProductFamily = value.ProductFamily, + ProductName = value.ProductName, + ProtocolMajor = value.ProtocolMajor, + ProtocolMinor = value.ProtocolMinor, + SupportedGroups = value.SupportedGroups, + Version = new() { - return $"{ImageWidth}x{ImageLength} {PixelType} {Compression} {BitsPerPixel}bpp"; + Country = value.Version.Country, + Info = value.Version.Info, + Language = value.Version.Language, + MajorNum = value.Version.MajorNum, + MinorNum = value.Version.MinorNum, } - } - - partial struct TW_SETUPMEMXFER + }; + public static implicit operator TW_IDENTITY_MACOSX(TW_IDENTITY_LEGACY value) => new() { - /// - /// Determines the best buffer size from values - /// specified by source - /// - /// - public uint DetermineBufferSize() + Id = value.Id, + Manufacturer = value.Manufacturer, + ProductFamily = value.ProductFamily, + ProductName = value.ProductName, + ProtocolMajor = value.ProtocolMajor, + ProtocolMinor = value.ProtocolMinor, + SupportedGroups = value.SupportedGroups, + Version = new() { - if (Preferred != TWConst.TWON_DONTCARE32) return Preferred; - if (MaxBufSize != TWConst.TWON_DONTCARE32) return MaxBufSize; - if (MinBufSize != TWConst.TWON_DONTCARE32) return MinBufSize; - // default to 16 kb if source doesn't really want to say what it needs - return 1024 * 16; + Country = value.Version.Country, + Info = value.Version.Info, + Language = value.Version.Language, + MajorNum = value.Version.MajorNum, + MinorNum = value.Version.MinorNum, } - } + }; +} - partial struct TW_IMAGEMEMXFER +partial struct TW_VERSION +{ + public override string ToString() { - /// - /// Get a don't care version for app use. - /// - /// - public static TW_IMAGEMEMXFER DONTCARE() - { - return new TW_IMAGEMEMXFER - { - BytesPerRow = TWConst.TWON_DONTCARE32, - BytesWritten = TWConst.TWON_DONTCARE32, - Columns = TWConst.TWON_DONTCARE32, - Compression = TWConst.TWON_DONTCARE16, - Rows = TWConst.TWON_DONTCARE32, - XOffset = TWConst.TWON_DONTCARE32, - YOffset = TWConst.TWON_DONTCARE32, - }; - } - } - - partial struct TW_IMAGEMEMXFER_MACOSX - { - /// - /// Get a don't care version for app use. - /// - /// - public static TW_IMAGEMEMXFER_MACOSX DONTCARE() - { - return new TW_IMAGEMEMXFER_MACOSX - { - BytesPerRow = TWConst.TWON_DONTCARE32, - BytesWritten = TWConst.TWON_DONTCARE32, - Columns = TWConst.TWON_DONTCARE32, - Compression = TWConst.TWON_DONTCARE32, - Rows = TWConst.TWON_DONTCARE32, - XOffset = TWConst.TWON_DONTCARE32, - YOffset = TWConst.TWON_DONTCARE32, - }; - } - } - - partial struct TW_DEVICEEVENT - { - // provide casted versions over raw value - - public TWDE Event { get { return (TWDE)_Event; } } - - public TWFL FlashUsed2 { get { return (TWFL)_FlashUsed2; } } - } - - - /// - /// Container for querying ext image info. After querying and done with - /// the data you must call to - /// free the memory allocated. - /// - public partial struct TW_EXTIMAGEINFO - { - /// - /// A quick way to create a query object with only values. - /// Limit is 100 at this time. - /// - /// - /// - public static TW_EXTIMAGEINFO CreateRequest(params TWEI[] infoNames) - { - if (infoNames == null || infoNames.Length == 0) return default; - if (infoNames.Length > 100) throw new InvalidOperationException("Cannot query more than 100 TWEIs at this time."); - - TW_EXTIMAGEINFO container = new() - { - NumInfos = (uint)infoNames.Length, - }; - - for (var i = 0; i < infoNames.Length; i++) - { - TW_INFO info = new() { InfoId = infoNames[i] }; - container.Set(i, ref info); - } - return container; - } - - /// - /// Reads the info out of this as array. - /// - /// - public TW_INFO[] AsInfos() - { - if (NumInfos == 0) return Array.Empty(); - - var arr = new TW_INFO[NumInfos]; - for (var i = 0; i < NumInfos; i++) - { - TW_INFO blah = default; - Get(i, ref blah); - arr[i] = blah; - } - return arr; - } - - /// - /// Frees all data contained here. - /// - /// - public void Free(IMemoryManager memMgr) - { - #region don't open this - Info_000.Free(memMgr); - Info_001.Free(memMgr); - Info_002.Free(memMgr); - Info_003.Free(memMgr); - Info_004.Free(memMgr); - Info_005.Free(memMgr); - Info_006.Free(memMgr); - Info_007.Free(memMgr); - Info_008.Free(memMgr); - Info_009.Free(memMgr); - Info_010.Free(memMgr); - Info_011.Free(memMgr); - Info_012.Free(memMgr); - Info_013.Free(memMgr); - Info_014.Free(memMgr); - Info_015.Free(memMgr); - Info_016.Free(memMgr); - Info_017.Free(memMgr); - Info_018.Free(memMgr); - Info_019.Free(memMgr); - Info_020.Free(memMgr); - Info_021.Free(memMgr); - Info_022.Free(memMgr); - Info_023.Free(memMgr); - Info_024.Free(memMgr); - Info_025.Free(memMgr); - Info_026.Free(memMgr); - Info_027.Free(memMgr); - Info_028.Free(memMgr); - Info_029.Free(memMgr); - Info_030.Free(memMgr); - Info_031.Free(memMgr); - Info_032.Free(memMgr); - Info_033.Free(memMgr); - Info_034.Free(memMgr); - Info_035.Free(memMgr); - Info_036.Free(memMgr); - Info_037.Free(memMgr); - Info_038.Free(memMgr); - Info_039.Free(memMgr); - Info_040.Free(memMgr); - Info_041.Free(memMgr); - Info_042.Free(memMgr); - Info_043.Free(memMgr); - Info_044.Free(memMgr); - Info_045.Free(memMgr); - Info_046.Free(memMgr); - Info_047.Free(memMgr); - Info_048.Free(memMgr); - Info_049.Free(memMgr); - Info_050.Free(memMgr); - Info_051.Free(memMgr); - Info_052.Free(memMgr); - Info_053.Free(memMgr); - Info_054.Free(memMgr); - Info_055.Free(memMgr); - Info_056.Free(memMgr); - Info_057.Free(memMgr); - Info_058.Free(memMgr); - Info_059.Free(memMgr); - Info_060.Free(memMgr); - Info_061.Free(memMgr); - Info_062.Free(memMgr); - Info_063.Free(memMgr); - Info_064.Free(memMgr); - Info_065.Free(memMgr); - Info_066.Free(memMgr); - Info_067.Free(memMgr); - Info_068.Free(memMgr); - Info_069.Free(memMgr); - Info_070.Free(memMgr); - Info_071.Free(memMgr); - Info_072.Free(memMgr); - Info_073.Free(memMgr); - Info_074.Free(memMgr); - Info_075.Free(memMgr); - Info_076.Free(memMgr); - Info_077.Free(memMgr); - Info_078.Free(memMgr); - Info_079.Free(memMgr); - Info_080.Free(memMgr); - Info_081.Free(memMgr); - Info_082.Free(memMgr); - Info_083.Free(memMgr); - Info_084.Free(memMgr); - Info_085.Free(memMgr); - Info_086.Free(memMgr); - Info_087.Free(memMgr); - Info_088.Free(memMgr); - Info_089.Free(memMgr); - Info_090.Free(memMgr); - Info_091.Free(memMgr); - Info_092.Free(memMgr); - Info_093.Free(memMgr); - Info_094.Free(memMgr); - Info_095.Free(memMgr); - Info_096.Free(memMgr); - Info_097.Free(memMgr); - Info_098.Free(memMgr); - Info_099.Free(memMgr); - #endregion - } - - } - - partial struct TW_INFO - { - /// - /// Quick check to see if the pointer is really - /// a pointer or actual data (ugh). - /// - public bool IsDataAPointer => - ItemType == TWTY.HANDLE || (ItemType.GetItemTypeSize() * NumItems) > IntPtr.Size; // should it be intptr.size or just 4? - - /// - /// Try to read out the item as the type specified in . - /// This ONLY works if the data is not a pointer (see ). - /// For pointers you'd read it yourself with - /// . - /// Unless it's a handle () to non-twain-strings, then you'd use - /// . - /// - /// - /// - public unsafe TValue ReadNonPointerData() where TValue : struct - { - if (ReturnCode != TWRC.SUCCESS || NumItems == 0 || IsDataAPointer) return default; - - // we can try a trick and make a pointer to this numeric data - // and re-use our pointer reader. There's a good chance this is wrong in many ways. - // TODO: test this idea in some unit test - var value = TWPlatform.Is32bit ? Item.ToUInt32() : Item.ToUInt64(); // the value should be 32bit from the spec but not sure how it'll work in 64bit - - var fakePtr = (IntPtr)(&value); - - return fakePtr.ReadTWTYData(ItemType, 0); - } - - /// - /// Try to read a null-terminated string from the item. - /// - /// - /// If item is an array specify which string to read - /// Pass a value if you know how long it should be. - /// - public unsafe string? ReadHandleString(IMemoryManager memMgr, int index = 0, int lengthHint = -1) - { - if (index < 0 || index >= NumItems || !IsDataAPointer) return default; - - // why is twain being difficult and not use TW_STR* like a normal person. - // what even is the encoding for those things? Imma yolo it. - string? value; - var itemAsPtr = (IntPtr)Item.ToPointer(); // this is also iffy - - if (NumItems == 1) - { - // if 1, item is already the pointer to the string - value = LockAndReadNullTerminatedString(memMgr, itemAsPtr, lengthHint); - } - else - { - // if more than 1, item points to an array of pointers that each points to their own string - var lockPtr = memMgr.Lock(itemAsPtr); - lockPtr += (IntPtr.Size * index); - // is this even correct? I hope it is - var subItemPtr = Marshal.PtrToStructure(lockPtr); - value = LockAndReadNullTerminatedString(memMgr, subItemPtr, lengthHint); - memMgr.Unlock(itemAsPtr); - } - return value; - } - - private string? LockAndReadNullTerminatedString(IMemoryManager memMgr, IntPtr data, int lengthHint = -1) - { - var lockPtr = memMgr.Lock(data); - // yolo as ansi, should work in most cases - var value = lengthHint > 0 ? Marshal.PtrToStringAnsi(lockPtr, lengthHint) : Marshal.PtrToStringAnsi(lockPtr); - memMgr.Unlock(data); - return value; - } - - /// - /// Frees all DS-allocated memory if necessary. - /// - /// - internal unsafe void Free(IMemoryManager memMgr) - { - if (ReturnCode != TWRC.SUCCESS || !IsDataAPointer) return; - - var itemAsPtr = (IntPtr)Item.ToPointer(); // this is also iffy - if (ItemType == TWTY.HANDLE && NumItems > 1) - { - // must go into each handle in the array and free them individually :( - var lockPtr = memMgr.Lock(itemAsPtr); - for (var i = 0; i < NumItems; i++) - { - // is this even correct? I hope it is - var subItemPtr = Marshal.PtrToStructure(lockPtr); - memMgr.Free(subItemPtr); - lockPtr += IntPtr.Size; - } - } - memMgr.Free(itemAsPtr); - Item = UIntPtr.Zero; - } + return $"{MajorNum}.{MinorNum}"; + } +} + +partial struct TW_STATUSUTF8 +{ + /// + /// Frees the memory if necessary. + /// + /// + public void Free(IMemoryManager mgr) + { + // session already checks for zero + mgr.Free(UTF8string); + UTF8string = IntPtr.Zero; + } + + /// + /// Tries to read the text content and optionally frees the memory. + /// + /// + /// Whether to free the pointer after reads. + /// + public string? Read(IMemoryManager mgr, bool freeMemory = true) + { + string? val = null; + if (UTF8string != IntPtr.Zero && Size > 0) + { + val = UTF8string.PtrToStringUTF8(mgr, (int)Size); + } + if (freeMemory) Free(mgr); + return val; + } +} + +partial struct TW_CAPABILITY +{ + public TW_CAPABILITY(CAP cap) + { + Cap = cap; + ConType = (TWON)TWConst.TWON_DONTCARE16; + } + + /// + /// Frees the memory if necessary. + /// + /// + public void Free(IMemoryManager mgr) + { + // session already checks for zero + mgr.Free(hContainer); + hContainer = IntPtr.Zero; + } +} + +partial struct TW_IMAGEINFO +{ + public override string ToString() + { + return $"{ImageWidth}x{ImageLength} {PixelType} {Compression} {BitsPerPixel}bpp"; + } +} + +partial struct TW_SETUPMEMXFER +{ + /// + /// Determines the best buffer size from values + /// specified by source + /// + /// + public uint DetermineBufferSize() + { + if (Preferred != TWConst.TWON_DONTCARE32) return Preferred; + if (MaxBufSize != TWConst.TWON_DONTCARE32) return MaxBufSize; + if (MinBufSize != TWConst.TWON_DONTCARE32) return MinBufSize; + // default to 16 kb if source doesn't really want to say what it needs + return 1024 * 16; + } +} + +partial struct TW_IMAGEMEMXFER +{ + /// + /// Get a don't care version for app use. + /// + /// + public static TW_IMAGEMEMXFER DONTCARE() + { + return new TW_IMAGEMEMXFER + { + BytesPerRow = TWConst.TWON_DONTCARE32, + BytesWritten = TWConst.TWON_DONTCARE32, + Columns = TWConst.TWON_DONTCARE32, + Compression = TWConst.TWON_DONTCARE16, + Rows = TWConst.TWON_DONTCARE32, + XOffset = TWConst.TWON_DONTCARE32, + YOffset = TWConst.TWON_DONTCARE32, + }; + } +} + +partial struct TW_IMAGEMEMXFER_MACOSX +{ + /// + /// Get a don't care version for app use. + /// + /// + public static TW_IMAGEMEMXFER_MACOSX DONTCARE() + { + return new TW_IMAGEMEMXFER_MACOSX + { + BytesPerRow = TWConst.TWON_DONTCARE32, + BytesWritten = TWConst.TWON_DONTCARE32, + Columns = TWConst.TWON_DONTCARE32, + Compression = TWConst.TWON_DONTCARE32, + Rows = TWConst.TWON_DONTCARE32, + XOffset = TWConst.TWON_DONTCARE32, + YOffset = TWConst.TWON_DONTCARE32, + }; + } +} + +partial struct TW_DEVICEEVENT +{ + // provide casted versions over raw value + + public TWDE Event { get { return (TWDE)_Event; } } + + public TWFL FlashUsed2 { get { return (TWFL)_FlashUsed2; } } +} + + +/// +/// Container for querying ext image info. After querying and done with +/// the data you must call to +/// free the memory allocated. +/// +public partial struct TW_EXTIMAGEINFO +{ + /// + /// A quick way to create a query object with only values. + /// Limit is 100 at this time. + /// + /// + /// + public static TW_EXTIMAGEINFO CreateRequest(params TWEI[] infoNames) + { + if (infoNames == null || infoNames.Length == 0) return default; + if (infoNames.Length > 100) throw new InvalidOperationException("Cannot query more than 100 TWEIs at this time."); + + TW_EXTIMAGEINFO container = new() + { + NumInfos = (uint)infoNames.Length, + }; + + for (var i = 0; i < infoNames.Length; i++) + { + TW_INFO info = new() { InfoId = infoNames[i] }; + container.Set(i, ref info); + } + return container; + } + + /// + /// Reads the info out of this as array. + /// + /// + public TW_INFO[] AsInfos() + { + if (NumInfos == 0) return Array.Empty(); + + var arr = new TW_INFO[NumInfos]; + for (var i = 0; i < NumInfos; i++) + { + TW_INFO blah = default; + Get(i, ref blah); + arr[i] = blah; + } + return arr; + } + + /// + /// Frees all data contained here. + /// + /// + public void Free(IMemoryManager memMgr) + { + #region don't open this + Info_000.Free(memMgr); + Info_001.Free(memMgr); + Info_002.Free(memMgr); + Info_003.Free(memMgr); + Info_004.Free(memMgr); + Info_005.Free(memMgr); + Info_006.Free(memMgr); + Info_007.Free(memMgr); + Info_008.Free(memMgr); + Info_009.Free(memMgr); + Info_010.Free(memMgr); + Info_011.Free(memMgr); + Info_012.Free(memMgr); + Info_013.Free(memMgr); + Info_014.Free(memMgr); + Info_015.Free(memMgr); + Info_016.Free(memMgr); + Info_017.Free(memMgr); + Info_018.Free(memMgr); + Info_019.Free(memMgr); + Info_020.Free(memMgr); + Info_021.Free(memMgr); + Info_022.Free(memMgr); + Info_023.Free(memMgr); + Info_024.Free(memMgr); + Info_025.Free(memMgr); + Info_026.Free(memMgr); + Info_027.Free(memMgr); + Info_028.Free(memMgr); + Info_029.Free(memMgr); + Info_030.Free(memMgr); + Info_031.Free(memMgr); + Info_032.Free(memMgr); + Info_033.Free(memMgr); + Info_034.Free(memMgr); + Info_035.Free(memMgr); + Info_036.Free(memMgr); + Info_037.Free(memMgr); + Info_038.Free(memMgr); + Info_039.Free(memMgr); + Info_040.Free(memMgr); + Info_041.Free(memMgr); + Info_042.Free(memMgr); + Info_043.Free(memMgr); + Info_044.Free(memMgr); + Info_045.Free(memMgr); + Info_046.Free(memMgr); + Info_047.Free(memMgr); + Info_048.Free(memMgr); + Info_049.Free(memMgr); + Info_050.Free(memMgr); + Info_051.Free(memMgr); + Info_052.Free(memMgr); + Info_053.Free(memMgr); + Info_054.Free(memMgr); + Info_055.Free(memMgr); + Info_056.Free(memMgr); + Info_057.Free(memMgr); + Info_058.Free(memMgr); + Info_059.Free(memMgr); + Info_060.Free(memMgr); + Info_061.Free(memMgr); + Info_062.Free(memMgr); + Info_063.Free(memMgr); + Info_064.Free(memMgr); + Info_065.Free(memMgr); + Info_066.Free(memMgr); + Info_067.Free(memMgr); + Info_068.Free(memMgr); + Info_069.Free(memMgr); + Info_070.Free(memMgr); + Info_071.Free(memMgr); + Info_072.Free(memMgr); + Info_073.Free(memMgr); + Info_074.Free(memMgr); + Info_075.Free(memMgr); + Info_076.Free(memMgr); + Info_077.Free(memMgr); + Info_078.Free(memMgr); + Info_079.Free(memMgr); + Info_080.Free(memMgr); + Info_081.Free(memMgr); + Info_082.Free(memMgr); + Info_083.Free(memMgr); + Info_084.Free(memMgr); + Info_085.Free(memMgr); + Info_086.Free(memMgr); + Info_087.Free(memMgr); + Info_088.Free(memMgr); + Info_089.Free(memMgr); + Info_090.Free(memMgr); + Info_091.Free(memMgr); + Info_092.Free(memMgr); + Info_093.Free(memMgr); + Info_094.Free(memMgr); + Info_095.Free(memMgr); + Info_096.Free(memMgr); + Info_097.Free(memMgr); + Info_098.Free(memMgr); + Info_099.Free(memMgr); + #endregion + } + +} + +partial struct TW_INFO +{ + /// + /// Quick check to see if the pointer is really + /// a pointer or actual data (ugh). + /// + public bool IsDataAPointer => + ItemType == TWTY.HANDLE || (ItemType.GetItemTypeSize() * NumItems) > IntPtr.Size; // should it be intptr.size or just 4? + + /// + /// Try to read out the item as the type specified in . + /// This ONLY works if the data is not a pointer (see ). + /// For pointers you'd read it yourself with + /// . + /// Unless it's a handle () to non-twain-strings, then you'd use + /// . + /// + /// + /// + public unsafe TValue ReadNonPointerData() where TValue : struct + { + if (ReturnCode != TWRC.SUCCESS || NumItems == 0 || IsDataAPointer) return default; + + // we can try a trick and make a pointer to this numeric data + // and re-use our pointer reader. There's a good chance this is wrong in many ways. + // TODO: test this idea in some unit test + var value = TWPlatform.Is32bit ? Item.ToUInt32() : Item.ToUInt64(); // the value should be 32bit from the spec but not sure how it'll work in 64bit + + var fakePtr = (IntPtr)(&value); + + return fakePtr.ReadTWTYData(ItemType, 0); + } + + /// + /// Try to read a null-terminated string from the item. + /// + /// + /// If item is an array specify which string to read + /// Pass a value if you know how long it should be. + /// + public unsafe string? ReadHandleString(IMemoryManager memMgr, int index = 0, int lengthHint = -1) + { + if (index < 0 || index >= NumItems || !IsDataAPointer) return default; + + // why is twain being difficult and not use TW_STR* like a normal person. + // what even is the encoding for those things? Imma yolo it. + string? value; + var itemAsPtr = (IntPtr)Item.ToPointer(); // this is also iffy + + if (NumItems == 1) + { + // if 1, item is already the pointer to the string + value = LockAndReadNullTerminatedString(memMgr, itemAsPtr, lengthHint); + } + else + { + // if more than 1, item points to an array of pointers that each points to their own string + var lockPtr = memMgr.Lock(itemAsPtr); + lockPtr += (IntPtr.Size * index); + // is this even correct? I hope it is + var subItemPtr = Marshal.PtrToStructure(lockPtr); + value = LockAndReadNullTerminatedString(memMgr, subItemPtr, lengthHint); + memMgr.Unlock(itemAsPtr); + } + return value; + } + + private string? LockAndReadNullTerminatedString(IMemoryManager memMgr, IntPtr data, int lengthHint = -1) + { + var lockPtr = memMgr.Lock(data); + // yolo as ansi, should work in most cases + var value = lengthHint > 0 ? Marshal.PtrToStringAnsi(lockPtr, lengthHint) : Marshal.PtrToStringAnsi(lockPtr); + memMgr.Unlock(data); + return value; + } + + /// + /// Frees all DS-allocated memory if necessary. + /// + /// + internal unsafe void Free(IMemoryManager memMgr) + { + if (ReturnCode != TWRC.SUCCESS || !IsDataAPointer) return; + + var itemAsPtr = (IntPtr)Item.ToPointer(); // this is also iffy + if (ItemType == TWTY.HANDLE && NumItems > 1) + { + // must go into each handle in the array and free them individually :( + var lockPtr = memMgr.Lock(itemAsPtr); + for (var i = 0; i < NumItems; i++) + { + // is this even correct? I hope it is + var subItemPtr = Marshal.PtrToStructure(lockPtr); + memMgr.Free(subItemPtr); + lockPtr += IntPtr.Size; + } + } + memMgr.Free(itemAsPtr); + Item = UIntPtr.Zero; } } diff --git a/src/NTwain/Data/ValueReader.cs b/src/NTwain/Data/ValueReader.cs index 66eba1e..a308808 100644 --- a/src/NTwain/Data/ValueReader.cs +++ b/src/NTwain/Data/ValueReader.cs @@ -4,749 +4,748 @@ using System.IO; using System.Runtime.InteropServices; using System.Text; -namespace NTwain.Data +namespace NTwain.Data; + +/// +/// Contains methods for reading pointers into various things. +/// +public static class ValueReader { /// - /// Contains methods for reading pointers into various things. + /// Reads pointer as UTF8 string. /// - public static class ValueReader + /// Pointer to string. + /// + /// Number of bytes to read. + /// + public static unsafe string? PtrToStringUTF8(this IntPtr data, IMemoryManager memMgr, int length) { - /// - /// Reads pointer as UTF8 string. - /// - /// Pointer to string. - /// - /// Number of bytes to read. - /// - public static unsafe string? PtrToStringUTF8(this IntPtr data, IMemoryManager memMgr, int length) + string? val = null; + var locked = memMgr.Lock(data); + if (locked != IntPtr.Zero) { - string? val = null; - var locked = memMgr.Lock(data); - if (locked != IntPtr.Zero) + try { - try - { #if NETFRAMEWORK - // safe method but with 2 copies (arr and parsed string) - //var bytes = new byte[length]; - //Marshal.Copy(locked, bytes, 0, bytes.Length); - //val = Encoding.UTF8.GetString(bytes); + // safe method but with 2 copies (arr and parsed string) + //var bytes = new byte[length]; + //Marshal.Copy(locked, bytes, 0, bytes.Length); + //val = Encoding.UTF8.GetString(bytes); - // does this work? - val = Encoding.UTF8.GetString((byte*)locked, length); + // does this work? + val = Encoding.UTF8.GetString((byte*)locked, length); #else - val = Marshal.PtrToStringUTF8(locked, length); + val = Marshal.PtrToStringUTF8(locked, length); #endif - } - finally - { - memMgr.Unlock(data); - } - } - return val; - } - - static T MarshalTo(IntPtr ptr) => Marshal.PtrToStructure(ptr)!; - - - // these contain parts from the original TWAIN.CapabilityToCsv() - - public static TWTY DetermineValueType(this ref TW_CAPABILITY cap, IMemoryManager memMgr, bool freeMemory = true) - { - var type = TWTY.Invalid; - - - var lockedPtr = memMgr.Lock(cap.hContainer); - - try - { - if (TWPlatform.IsMacOSX) - { - type = (TWTY)(ushort)(uint)Marshal.ReadInt32(lockedPtr); - - } - else - { - type = (TWTY)(ushort)Marshal.ReadInt16(lockedPtr); - } } finally { - if (lockedPtr != IntPtr.Zero) memMgr.Unlock(cap.hContainer); - if (freeMemory) - { - memMgr.Free(cap.hContainer); - cap.hContainer = IntPtr.Zero; - } - } - - return type; - } - - - /// - /// Reads a boxed one value out of a cap. This can only be done once if memory is freed. - /// - /// - /// - /// - /// - public static object? ReadOneValueBoxed(this ref TW_CAPABILITY cap, IMemoryManager memMgr, bool freeMemory = true) - { - if (cap.ConType != TWON.ONEVALUE || cap.hContainer == IntPtr.Zero) return default; - - var lockedPtr = memMgr.Lock(cap.hContainer); - - try - { - TWTY itemType; - // Mac has a level of indirection and a different structure (ick)... - if (TWPlatform.IsMacOSX) - { - // Crack the container... - var onevalue = MarshalTo(lockedPtr); - itemType = (TWTY)onevalue.ItemType; - lockedPtr += Marshal.SizeOf(onevalue); - } - else - { - // Crack the container... - var onevalue = MarshalTo(lockedPtr); - itemType = onevalue.ItemType; - lockedPtr += Marshal.SizeOf(onevalue); - } - - return ReadTWTYDataBoxed(lockedPtr, itemType, 0); - } - finally - { - if (lockedPtr != IntPtr.Zero) memMgr.Unlock(cap.hContainer); - if (freeMemory) - { - memMgr.Free(cap.hContainer); - cap.hContainer = IntPtr.Zero; - } + memMgr.Unlock(data); } } - - /// - /// Reads a one value out of a cap. This can only be done once if memory is freed. - /// - /// - /// - /// - /// - /// - public static TValue ReadOneValue(this ref TW_CAPABILITY cap, IMemoryManager memMgr, bool freeMemory = true) where TValue : struct - { - if (cap.ConType != TWON.ONEVALUE || cap.hContainer == IntPtr.Zero) return default; - - var lockedPtr = memMgr.Lock(cap.hContainer); - - try - { - TWTY itemType; - // Mac has a level of indirection and a different structure (ick)... - if (TWPlatform.IsMacOSX) - { - // Crack the container... - var onevalue = MarshalTo(lockedPtr); - itemType = (TWTY)onevalue.ItemType; - lockedPtr += Marshal.SizeOf(onevalue); - } - else - { - // Crack the container... - var onevalue = MarshalTo(lockedPtr); - itemType = onevalue.ItemType; - lockedPtr += Marshal.SizeOf(onevalue); - } - - return ReadTWTYData(lockedPtr, itemType, 0); - } - finally - { - if (lockedPtr != IntPtr.Zero) memMgr.Unlock(cap.hContainer); - if (freeMemory) - { - memMgr.Free(cap.hContainer); - cap.hContainer = IntPtr.Zero; - } - } - } - - public static Enumeration ReadEnumerationBoxed(this ref TW_CAPABILITY cap, IMemoryManager memMgr, bool freeMemory = true) - { - Enumeration retVal = new(); - - if (cap.ConType != TWON.ENUMERATION || cap.hContainer == IntPtr.Zero) return retVal; - - var lockedPtr = memMgr.Lock(cap.hContainer); - - try - { - TWTY itemType; - int count = 0; - - // Mac has a level of indirection and a different structure (ick)... - if (TWPlatform.IsMacOSX) - { - // Crack the container... - var twenumerationmacosx = MarshalTo(lockedPtr); - itemType = (TWTY)twenumerationmacosx.ItemType; - count = (int)twenumerationmacosx.NumItems; - retVal.DefaultIndex = (int)twenumerationmacosx.DefaultIndex; - retVal.CurrentIndex = (int)twenumerationmacosx.CurrentIndex; - lockedPtr += Marshal.SizeOf(twenumerationmacosx); - } - // Windows or the 2.4+ Linux DSM... - else - { - // Crack the container... - var twenumeration = MarshalTo(lockedPtr); - itemType = twenumeration.ItemType; - count = (int)twenumeration.NumItems; - retVal.DefaultIndex = (int)twenumeration.DefaultIndex; - retVal.CurrentIndex = (int)twenumeration.CurrentIndex; - lockedPtr += Marshal.SizeOf(twenumeration); - } - // The -2.3 Linux DSM... - //else if (twain.m_blFound020302Dsm64bit && (twain.m_linuxdsm == TWAIN.LinuxDsm.Is020302Dsm64bit)) - //{ - // // Crack the container... - // var twenumerationlinux64 = MarshalTo(lockedPtr); - // itemType = twenumerationlinux64.ItemType; - // count = (int)twenumerationlinux64.NumItems; - // retVal.DefaultIndex = (int)twenumerationlinux64.DefaultIndex; - // retVal.CurrentIndex = (int)twenumerationlinux64.CurrentIndex; - // lockedPtr += Marshal.SizeOf(twenumerationlinux64); - //} - // This shouldn't be possible, but what the hey... - //else - //{ - // Log.Error("This is serious, you win a cookie for getting here..."); - // return retVal; - //} - - retVal.Items = new object[count]; - - for (var i = 0; i < count; i++) - { - retVal.Items[i] = ReadTWTYDataBoxed(lockedPtr, itemType, i); - } - } - finally - { - if (lockedPtr != IntPtr.Zero) memMgr.Unlock(cap.hContainer); - if (freeMemory) - { - memMgr.Free(cap.hContainer); - cap.hContainer = IntPtr.Zero; - } - } - return retVal; - } - - public static Enumeration ReadEnumeration(this ref TW_CAPABILITY cap, IMemoryManager memMgr, bool freeMemory = true) where TValue : struct - { - Enumeration retVal = new(); - - if (cap.ConType != TWON.ENUMERATION || cap.hContainer == IntPtr.Zero) return retVal; - - var lockedPtr = memMgr.Lock(cap.hContainer); - - try - { - TWTY itemType; - int count = 0; - - // Mac has a level of indirection and a different structure (ick)... - if (TWPlatform.IsMacOSX) - { - // Crack the container... - var twenumerationmacosx = MarshalTo(lockedPtr); - itemType = (TWTY)twenumerationmacosx.ItemType; - count = (int)twenumerationmacosx.NumItems; - retVal.DefaultIndex = (int)twenumerationmacosx.DefaultIndex; - retVal.CurrentIndex = (int)twenumerationmacosx.CurrentIndex; - lockedPtr += Marshal.SizeOf(twenumerationmacosx); - } - // Windows or the 2.4+ Linux DSM... - else - { - // Crack the container... - var twenumeration = MarshalTo(lockedPtr); - itemType = twenumeration.ItemType; - count = (int)twenumeration.NumItems; - retVal.DefaultIndex = (int)twenumeration.DefaultIndex; - retVal.CurrentIndex = (int)twenumeration.CurrentIndex; - lockedPtr += Marshal.SizeOf(twenumeration); - } - // The -2.3 Linux DSM... - //else if (twain.m_blFound020302Dsm64bit && (twain.m_linuxdsm == TWAIN.LinuxDsm.Is020302Dsm64bit)) - //{ - // // Crack the container... - // var twenumerationlinux64 = MarshalTo(lockedPtr); - // itemType = twenumerationlinux64.ItemType; - // count = (int)twenumerationlinux64.NumItems; - // retVal.DefaultIndex = (int)twenumerationlinux64.DefaultIndex; - // retVal.CurrentIndex = (int)twenumerationlinux64.CurrentIndex; - // lockedPtr += Marshal.SizeOf(twenumerationlinux64); - //} - // This shouldn't be possible, but what the hey... - //else - //{ - // Log.Error("This is serious, you win a cookie for getting here..."); - // return retVal; - //} - - retVal.Items = new TValue[count]; - - for (var i = 0; i < count; i++) - { - retVal.Items[i] = ReadTWTYData(lockedPtr, itemType, i); - } - } - finally - { - if (lockedPtr != IntPtr.Zero) memMgr.Unlock(cap.hContainer); - if (freeMemory) - { - memMgr.Free(cap.hContainer); - cap.hContainer = IntPtr.Zero; - } - } - return retVal; - } - - public static IList ReadArrayBoxed(this ref TW_CAPABILITY cap, IMemoryManager memMgr, bool freeMemory = true) - { - if (cap.ConType != TWON.ARRAY || cap.hContainer == IntPtr.Zero) return Array.Empty(); - - var lockedPtr = memMgr.Lock(cap.hContainer); - - try - { - TWTY itemType; - uint count; - - // Mac has a level of indirection and a different structure (ick)... - if (TWPlatform.IsMacOSX) - { - // Crack the container... - var twarraymacosx = MarshalTo(lockedPtr); - itemType = (TWTY)twarraymacosx.ItemType; - count = twarraymacosx.NumItems; - lockedPtr += Marshal.SizeOf(twarraymacosx); - } - else - { - // Crack the container... - var twarray = MarshalTo(lockedPtr); - itemType = twarray.ItemType; - count = twarray.NumItems; - lockedPtr += Marshal.SizeOf(twarray); - } - - var arr = new object[count]; - for (var i = 0; i < count; i++) - { - arr[i] = ReadTWTYDataBoxed(lockedPtr, itemType, i); - } - return arr; - } - finally - { - if (lockedPtr != IntPtr.Zero) memMgr.Unlock(cap.hContainer); - if (freeMemory) - { - memMgr.Free(cap.hContainer); - cap.hContainer = IntPtr.Zero; - } - } - } - - public static IList ReadArray(this ref TW_CAPABILITY cap, IMemoryManager memMgr, bool freeMemory = true) where TValue : struct - { - if (cap.ConType != TWON.ARRAY || cap.hContainer == IntPtr.Zero) return Array.Empty(); - - var lockedPtr = memMgr.Lock(cap.hContainer); - - try - { - TWTY itemType; - uint count; - - // Mac has a level of indirection and a different structure (ick)... - if (TWPlatform.IsMacOSX) - { - // Crack the container... - var twarraymacosx = MarshalTo(lockedPtr); - itemType = (TWTY)twarraymacosx.ItemType; - count = twarraymacosx.NumItems; - lockedPtr += Marshal.SizeOf(twarraymacosx); - } - else - { - // Crack the container... - var twarray = MarshalTo(lockedPtr); - itemType = twarray.ItemType; - count = twarray.NumItems; - lockedPtr += Marshal.SizeOf(twarray); - } - - var arr = new TValue[count]; - for (var i = 0; i < count; i++) - { - arr[i] = ReadTWTYData(lockedPtr, itemType, i); - } - return arr; - } - finally - { - if (lockedPtr != IntPtr.Zero) memMgr.Unlock(cap.hContainer); - if (freeMemory) - { - memMgr.Free(cap.hContainer); - cap.hContainer = IntPtr.Zero; - } - } - } - - public static Range? ReadRangeBoxed(this ref TW_CAPABILITY cap, IMemoryManager memMgr, bool freeMemory = true) - { - if (cap.ConType != TWON.RANGE || cap.hContainer == IntPtr.Zero) return null; - - var lockedPtr = memMgr.Lock(cap.hContainer); - - try - { - TWTY itemType; - // Mac has a level of indirection and a different structure (ick)... - if (TWPlatform.IsMacOSX) - { - itemType = (TWTY)Marshal.ReadInt32(lockedPtr); - lockedPtr += 4; - } - else - { - // Windows or the 2.4+ Linux DSM... - itemType = (TWTY)Marshal.ReadInt16(lockedPtr); - lockedPtr += 2; - } - var minValue = ReadTWTYDataBoxed(lockedPtr, itemType, 0); - lockedPtr += 4; - var maxValue = ReadTWTYDataBoxed(lockedPtr, itemType, 0); - lockedPtr += 4; - var stepSize = ReadTWTYDataBoxed(lockedPtr, itemType, 0); - lockedPtr += 4; - var currentValue = ReadTWTYDataBoxed(lockedPtr, itemType, 0); - lockedPtr += 4; - var defaultValue = ReadTWTYDataBoxed(lockedPtr, itemType, 0); - lockedPtr += 4; - return new Range - { - MinValue = minValue, - MaxValue = maxValue, - StepSize = stepSize, - CurrentValue = currentValue, - DefaultValue = defaultValue - }; - } - finally - { - if (lockedPtr != IntPtr.Zero) memMgr.Unlock(cap.hContainer); - if (freeMemory) - { - memMgr.Free(cap.hContainer); - cap.hContainer = IntPtr.Zero; - } - } - } - - public static Range? ReadRange(this ref TW_CAPABILITY cap, IMemoryManager memMgr, bool freeMemory = true) where TValue : struct - { - if (cap.ConType != TWON.RANGE || cap.hContainer == IntPtr.Zero) return null; - - var lockedPtr = memMgr.Lock(cap.hContainer); - - try - { - TWTY itemType; - // Mac has a level of indirection and a different structure (ick)... - if (TWPlatform.IsMacOSX) - { - itemType = (TWTY)Marshal.ReadInt32(lockedPtr); - lockedPtr += 4; - } - else - { - // Windows or the 2.4+ Linux DSM... - itemType = (TWTY)Marshal.ReadInt16(lockedPtr); - lockedPtr += 2; - } - var minValue = ReadTWTYData(lockedPtr, itemType, 0); - lockedPtr += 4; - var maxValue = ReadTWTYData(lockedPtr, itemType, 0); - lockedPtr += 4; - var stepSize = ReadTWTYData(lockedPtr, itemType, 0); - lockedPtr += 4; - var currentValue = ReadTWTYData(lockedPtr, itemType, 0); - lockedPtr += 4; - var defaultValue = ReadTWTYData(lockedPtr, itemType, 0); - lockedPtr += 4; - return new Range - { - MinValue = minValue, - MaxValue = maxValue, - StepSize = stepSize, - CurrentValue = currentValue, - DefaultValue = defaultValue - }; - } - finally - { - if (lockedPtr != IntPtr.Zero) memMgr.Unlock(cap.hContainer); - if (freeMemory) - { - memMgr.Free(cap.hContainer); - cap.hContainer = IntPtr.Zero; - } - } - } - - /// - /// Read the pointer as string. This is for cap's one value string pointer - /// that - /// - /// - /// - /// - /// - public static string? ReadString(this ref TW_CAPABILITY cap, IMemoryManager memMgr, bool freeMemory = true) - { - if (cap.hContainer == IntPtr.Zero) return null; - - var lockedPtr = memMgr.Lock(cap.hContainer); - - try - { - if (cap.ConType == TWON.ONEVALUE) - { - TWTY itemType; - // Mac has a level of indirection and a different structure (ick)... - if (TWPlatform.IsMacOSX) - { - // Crack the container... - var onevalue = MarshalTo(lockedPtr); - itemType = (TWTY)onevalue.ItemType; - lockedPtr += Marshal.SizeOf(onevalue); - } - else - { - // Crack the container... - var onevalue = MarshalTo(lockedPtr); - itemType = onevalue.ItemType; - lockedPtr += Marshal.SizeOf(onevalue); - } - - switch (itemType) - { - case TWTY.STR32: - return MarshalTo(lockedPtr).ToString(); - case TWTY.STR64: - return MarshalTo(lockedPtr).ToString(); - case TWTY.STR128: - return MarshalTo(lockedPtr).ToString(); - case TWTY.STR255: - return MarshalTo(lockedPtr).ToString(); - case TWTY.HANDLE: - // TODO: how to determine the length of this thing??? - // null-terminated and encoded string? - // good chance this ain't right. - using (var stream = new MemoryStream()) - { - byte read = Marshal.ReadByte(lockedPtr); - while (read != 0) - { - stream.WriteByte(read); - read = Marshal.ReadByte(lockedPtr); - lockedPtr += 1; - } - // which one? - //return Encoding.Unicode.GetString(Encoding.Convert(Language.GetEncoding(), Encoding.Unicode, stream.ToArray())); - return Language.GetEncoding().GetString(stream.ToArray()); - } - } - } - } - finally - { - if (lockedPtr != IntPtr.Zero) memMgr.Unlock(cap.hContainer); - if (freeMemory) - { - memMgr.Free(cap.hContainer); - cap.hContainer = IntPtr.Zero; - } - } - return null; - } - - - - /// - /// Read the pointer content as a boxed value specified by , except . - /// - /// A locked pointer to the data pointer. If data is array this is the 0th item. - /// The twain type. - /// Index of the item if pointer is array. - /// - public static object ReadTWTYDataBoxed(this IntPtr intptr, TWTY type, int itemIndex) - { - switch (type) - { - default: - throw new NotSupportedException($"Unsupported item type {type} for reading."); - // TODO: verify if needs to read int32 for small types - case TWTY.HANDLE: - intptr += IntPtr.Size * itemIndex; - return MarshalTo(intptr); - case TWTY.INT8: - intptr += 1 * itemIndex; - return MarshalTo(intptr); - case TWTY.UINT8: - intptr += 1 * itemIndex; - return MarshalTo(intptr); - case TWTY.INT16: - intptr += 2 * itemIndex; - return MarshalTo(intptr); - case TWTY.BOOL: - case TWTY.UINT16: - intptr += 2 * itemIndex; - return MarshalTo(intptr); - case TWTY.INT32: - intptr += 4 * itemIndex; - return MarshalTo(intptr); - case TWTY.UINT32: - intptr += 4 * itemIndex; - return MarshalTo(intptr); - case TWTY.FIX32: - intptr += 4 * itemIndex; - return MarshalTo(intptr); - case TWTY.FRAME: - intptr += 16 * itemIndex; - return MarshalTo(intptr); - case TWTY.STR32: - intptr += TW_STR32.Size * itemIndex; - return MarshalTo(intptr); - case TWTY.STR64: - intptr += TW_STR64.Size * itemIndex; - return MarshalTo(intptr); - case TWTY.STR128: - intptr += TW_STR128.Size * itemIndex; - return MarshalTo(intptr); - case TWTY.STR255: - intptr += TW_STR255.Size * itemIndex; - return MarshalTo(intptr); - } - } - - /// - /// Read the pointer content as a value specified by , except . - /// - /// A locked pointer to the data pointer. If data is array this is the 0th item. - /// The twain type. - /// Index of the item if pointer is array. - /// - public static TValue ReadTWTYData(this IntPtr intptr, TWTY type, int itemIndex) where TValue : struct - { - var isEnum = typeof(TValue).IsEnum; - - switch (type) - { - default: - throw new NotSupportedException($"Unsupported item type {type} for reading."); - // TODO: verify if needs to read int32 for small types - case TWTY.HANDLE: - intptr += IntPtr.Size * itemIndex; - return MarshalTo(intptr); - case TWTY.INT8: - intptr += 1 * itemIndex; - if (isEnum) - { - return NumericToEnum(MarshalTo(intptr)); - } - return MarshalTo(intptr); - case TWTY.UINT8: - intptr += 1 * itemIndex; - if (isEnum) - { - return NumericToEnum(MarshalTo(intptr)); - } - return MarshalTo(intptr); - case TWTY.INT16: - intptr += 2 * itemIndex; - if (isEnum) - { - return NumericToEnum(MarshalTo(intptr)); - } - return MarshalTo(intptr); - case TWTY.BOOL: - case TWTY.UINT16: - intptr += 2 * itemIndex; - if (isEnum) - { - return NumericToEnum(MarshalTo(intptr)); - } - return MarshalTo(intptr); - case TWTY.INT32: - intptr += 4 * itemIndex; - if (isEnum) - { - return NumericToEnum(MarshalTo(intptr)); - } - return MarshalTo(intptr); - case TWTY.UINT32: - intptr += 4 * itemIndex; - if (isEnum) - { - return NumericToEnum(MarshalTo(intptr)); - } - return MarshalTo(intptr); - case TWTY.FIX32: - intptr += 4 * itemIndex; - return MarshalTo(intptr); - case TWTY.FRAME: - intptr += 16 * itemIndex; - return MarshalTo(intptr); - case TWTY.STR32: - intptr += TW_STR32.Size * itemIndex; - return MarshalTo(intptr); - case TWTY.STR64: - intptr += TW_STR64.Size * itemIndex; - return MarshalTo(intptr); - case TWTY.STR128: - intptr += TW_STR128.Size * itemIndex; - return MarshalTo(intptr); - case TWTY.STR255: - intptr += TW_STR255.Size * itemIndex; - return MarshalTo(intptr); - } - } - - static TEnum NumericToEnum(TNumber num) where TEnum : struct - { - // TODO: some caps returns a data type that's not the underlying datatype for the enum - // so foolproof way is to ToString() it and parse it as the enum type. - // this is bad for perf so find better way later - var str = num!.ToString(); - - if (Enum.TryParse(str, out TEnum parsed)) - { - return parsed; - } - return default; - } - + return val; } + + static T MarshalTo(IntPtr ptr) => Marshal.PtrToStructure(ptr)!; + + + // these contain parts from the original TWAIN.CapabilityToCsv() + + public static TWTY DetermineValueType(this ref TW_CAPABILITY cap, IMemoryManager memMgr, bool freeMemory = true) + { + var type = TWTY.Invalid; + + + var lockedPtr = memMgr.Lock(cap.hContainer); + + try + { + if (TWPlatform.IsMacOSX) + { + type = (TWTY)(ushort)(uint)Marshal.ReadInt32(lockedPtr); + + } + else + { + type = (TWTY)(ushort)Marshal.ReadInt16(lockedPtr); + } + } + finally + { + if (lockedPtr != IntPtr.Zero) memMgr.Unlock(cap.hContainer); + if (freeMemory) + { + memMgr.Free(cap.hContainer); + cap.hContainer = IntPtr.Zero; + } + } + + return type; + } + + + /// + /// Reads a boxed one value out of a cap. This can only be done once if memory is freed. + /// + /// + /// + /// + /// + public static object? ReadOneValueBoxed(this ref TW_CAPABILITY cap, IMemoryManager memMgr, bool freeMemory = true) + { + if (cap.ConType != TWON.ONEVALUE || cap.hContainer == IntPtr.Zero) return default; + + var lockedPtr = memMgr.Lock(cap.hContainer); + + try + { + TWTY itemType; + // Mac has a level of indirection and a different structure (ick)... + if (TWPlatform.IsMacOSX) + { + // Crack the container... + var onevalue = MarshalTo(lockedPtr); + itemType = (TWTY)onevalue.ItemType; + lockedPtr += Marshal.SizeOf(onevalue); + } + else + { + // Crack the container... + var onevalue = MarshalTo(lockedPtr); + itemType = onevalue.ItemType; + lockedPtr += Marshal.SizeOf(onevalue); + } + + return ReadTWTYDataBoxed(lockedPtr, itemType, 0); + } + finally + { + if (lockedPtr != IntPtr.Zero) memMgr.Unlock(cap.hContainer); + if (freeMemory) + { + memMgr.Free(cap.hContainer); + cap.hContainer = IntPtr.Zero; + } + } + } + + /// + /// Reads a one value out of a cap. This can only be done once if memory is freed. + /// + /// + /// + /// + /// + /// + public static TValue ReadOneValue(this ref TW_CAPABILITY cap, IMemoryManager memMgr, bool freeMemory = true) where TValue : struct + { + if (cap.ConType != TWON.ONEVALUE || cap.hContainer == IntPtr.Zero) return default; + + var lockedPtr = memMgr.Lock(cap.hContainer); + + try + { + TWTY itemType; + // Mac has a level of indirection and a different structure (ick)... + if (TWPlatform.IsMacOSX) + { + // Crack the container... + var onevalue = MarshalTo(lockedPtr); + itemType = (TWTY)onevalue.ItemType; + lockedPtr += Marshal.SizeOf(onevalue); + } + else + { + // Crack the container... + var onevalue = MarshalTo(lockedPtr); + itemType = onevalue.ItemType; + lockedPtr += Marshal.SizeOf(onevalue); + } + + return ReadTWTYData(lockedPtr, itemType, 0); + } + finally + { + if (lockedPtr != IntPtr.Zero) memMgr.Unlock(cap.hContainer); + if (freeMemory) + { + memMgr.Free(cap.hContainer); + cap.hContainer = IntPtr.Zero; + } + } + } + + public static Enumeration ReadEnumerationBoxed(this ref TW_CAPABILITY cap, IMemoryManager memMgr, bool freeMemory = true) + { + Enumeration retVal = new(); + + if (cap.ConType != TWON.ENUMERATION || cap.hContainer == IntPtr.Zero) return retVal; + + var lockedPtr = memMgr.Lock(cap.hContainer); + + try + { + TWTY itemType; + int count = 0; + + // Mac has a level of indirection and a different structure (ick)... + if (TWPlatform.IsMacOSX) + { + // Crack the container... + var twenumerationmacosx = MarshalTo(lockedPtr); + itemType = (TWTY)twenumerationmacosx.ItemType; + count = (int)twenumerationmacosx.NumItems; + retVal.DefaultIndex = (int)twenumerationmacosx.DefaultIndex; + retVal.CurrentIndex = (int)twenumerationmacosx.CurrentIndex; + lockedPtr += Marshal.SizeOf(twenumerationmacosx); + } + // Windows or the 2.4+ Linux DSM... + else + { + // Crack the container... + var twenumeration = MarshalTo(lockedPtr); + itemType = twenumeration.ItemType; + count = (int)twenumeration.NumItems; + retVal.DefaultIndex = (int)twenumeration.DefaultIndex; + retVal.CurrentIndex = (int)twenumeration.CurrentIndex; + lockedPtr += Marshal.SizeOf(twenumeration); + } + // The -2.3 Linux DSM... + //else if (twain.m_blFound020302Dsm64bit && (twain.m_linuxdsm == TWAIN.LinuxDsm.Is020302Dsm64bit)) + //{ + // // Crack the container... + // var twenumerationlinux64 = MarshalTo(lockedPtr); + // itemType = twenumerationlinux64.ItemType; + // count = (int)twenumerationlinux64.NumItems; + // retVal.DefaultIndex = (int)twenumerationlinux64.DefaultIndex; + // retVal.CurrentIndex = (int)twenumerationlinux64.CurrentIndex; + // lockedPtr += Marshal.SizeOf(twenumerationlinux64); + //} + // This shouldn't be possible, but what the hey... + //else + //{ + // Log.Error("This is serious, you win a cookie for getting here..."); + // return retVal; + //} + + retVal.Items = new object[count]; + + for (var i = 0; i < count; i++) + { + retVal.Items[i] = ReadTWTYDataBoxed(lockedPtr, itemType, i); + } + } + finally + { + if (lockedPtr != IntPtr.Zero) memMgr.Unlock(cap.hContainer); + if (freeMemory) + { + memMgr.Free(cap.hContainer); + cap.hContainer = IntPtr.Zero; + } + } + return retVal; + } + + public static Enumeration ReadEnumeration(this ref TW_CAPABILITY cap, IMemoryManager memMgr, bool freeMemory = true) where TValue : struct + { + Enumeration retVal = new(); + + if (cap.ConType != TWON.ENUMERATION || cap.hContainer == IntPtr.Zero) return retVal; + + var lockedPtr = memMgr.Lock(cap.hContainer); + + try + { + TWTY itemType; + int count = 0; + + // Mac has a level of indirection and a different structure (ick)... + if (TWPlatform.IsMacOSX) + { + // Crack the container... + var twenumerationmacosx = MarshalTo(lockedPtr); + itemType = (TWTY)twenumerationmacosx.ItemType; + count = (int)twenumerationmacosx.NumItems; + retVal.DefaultIndex = (int)twenumerationmacosx.DefaultIndex; + retVal.CurrentIndex = (int)twenumerationmacosx.CurrentIndex; + lockedPtr += Marshal.SizeOf(twenumerationmacosx); + } + // Windows or the 2.4+ Linux DSM... + else + { + // Crack the container... + var twenumeration = MarshalTo(lockedPtr); + itemType = twenumeration.ItemType; + count = (int)twenumeration.NumItems; + retVal.DefaultIndex = (int)twenumeration.DefaultIndex; + retVal.CurrentIndex = (int)twenumeration.CurrentIndex; + lockedPtr += Marshal.SizeOf(twenumeration); + } + // The -2.3 Linux DSM... + //else if (twain.m_blFound020302Dsm64bit && (twain.m_linuxdsm == TWAIN.LinuxDsm.Is020302Dsm64bit)) + //{ + // // Crack the container... + // var twenumerationlinux64 = MarshalTo(lockedPtr); + // itemType = twenumerationlinux64.ItemType; + // count = (int)twenumerationlinux64.NumItems; + // retVal.DefaultIndex = (int)twenumerationlinux64.DefaultIndex; + // retVal.CurrentIndex = (int)twenumerationlinux64.CurrentIndex; + // lockedPtr += Marshal.SizeOf(twenumerationlinux64); + //} + // This shouldn't be possible, but what the hey... + //else + //{ + // Log.Error("This is serious, you win a cookie for getting here..."); + // return retVal; + //} + + retVal.Items = new TValue[count]; + + for (var i = 0; i < count; i++) + { + retVal.Items[i] = ReadTWTYData(lockedPtr, itemType, i); + } + } + finally + { + if (lockedPtr != IntPtr.Zero) memMgr.Unlock(cap.hContainer); + if (freeMemory) + { + memMgr.Free(cap.hContainer); + cap.hContainer = IntPtr.Zero; + } + } + return retVal; + } + + public static IList ReadArrayBoxed(this ref TW_CAPABILITY cap, IMemoryManager memMgr, bool freeMemory = true) + { + if (cap.ConType != TWON.ARRAY || cap.hContainer == IntPtr.Zero) return Array.Empty(); + + var lockedPtr = memMgr.Lock(cap.hContainer); + + try + { + TWTY itemType; + uint count; + + // Mac has a level of indirection and a different structure (ick)... + if (TWPlatform.IsMacOSX) + { + // Crack the container... + var twarraymacosx = MarshalTo(lockedPtr); + itemType = (TWTY)twarraymacosx.ItemType; + count = twarraymacosx.NumItems; + lockedPtr += Marshal.SizeOf(twarraymacosx); + } + else + { + // Crack the container... + var twarray = MarshalTo(lockedPtr); + itemType = twarray.ItemType; + count = twarray.NumItems; + lockedPtr += Marshal.SizeOf(twarray); + } + + var arr = new object[count]; + for (var i = 0; i < count; i++) + { + arr[i] = ReadTWTYDataBoxed(lockedPtr, itemType, i); + } + return arr; + } + finally + { + if (lockedPtr != IntPtr.Zero) memMgr.Unlock(cap.hContainer); + if (freeMemory) + { + memMgr.Free(cap.hContainer); + cap.hContainer = IntPtr.Zero; + } + } + } + + public static IList ReadArray(this ref TW_CAPABILITY cap, IMemoryManager memMgr, bool freeMemory = true) where TValue : struct + { + if (cap.ConType != TWON.ARRAY || cap.hContainer == IntPtr.Zero) return Array.Empty(); + + var lockedPtr = memMgr.Lock(cap.hContainer); + + try + { + TWTY itemType; + uint count; + + // Mac has a level of indirection and a different structure (ick)... + if (TWPlatform.IsMacOSX) + { + // Crack the container... + var twarraymacosx = MarshalTo(lockedPtr); + itemType = (TWTY)twarraymacosx.ItemType; + count = twarraymacosx.NumItems; + lockedPtr += Marshal.SizeOf(twarraymacosx); + } + else + { + // Crack the container... + var twarray = MarshalTo(lockedPtr); + itemType = twarray.ItemType; + count = twarray.NumItems; + lockedPtr += Marshal.SizeOf(twarray); + } + + var arr = new TValue[count]; + for (var i = 0; i < count; i++) + { + arr[i] = ReadTWTYData(lockedPtr, itemType, i); + } + return arr; + } + finally + { + if (lockedPtr != IntPtr.Zero) memMgr.Unlock(cap.hContainer); + if (freeMemory) + { + memMgr.Free(cap.hContainer); + cap.hContainer = IntPtr.Zero; + } + } + } + + public static Range? ReadRangeBoxed(this ref TW_CAPABILITY cap, IMemoryManager memMgr, bool freeMemory = true) + { + if (cap.ConType != TWON.RANGE || cap.hContainer == IntPtr.Zero) return null; + + var lockedPtr = memMgr.Lock(cap.hContainer); + + try + { + TWTY itemType; + // Mac has a level of indirection and a different structure (ick)... + if (TWPlatform.IsMacOSX) + { + itemType = (TWTY)Marshal.ReadInt32(lockedPtr); + lockedPtr += 4; + } + else + { + // Windows or the 2.4+ Linux DSM... + itemType = (TWTY)Marshal.ReadInt16(lockedPtr); + lockedPtr += 2; + } + var minValue = ReadTWTYDataBoxed(lockedPtr, itemType, 0); + lockedPtr += 4; + var maxValue = ReadTWTYDataBoxed(lockedPtr, itemType, 0); + lockedPtr += 4; + var stepSize = ReadTWTYDataBoxed(lockedPtr, itemType, 0); + lockedPtr += 4; + var currentValue = ReadTWTYDataBoxed(lockedPtr, itemType, 0); + lockedPtr += 4; + var defaultValue = ReadTWTYDataBoxed(lockedPtr, itemType, 0); + lockedPtr += 4; + return new Range + { + MinValue = minValue, + MaxValue = maxValue, + StepSize = stepSize, + CurrentValue = currentValue, + DefaultValue = defaultValue + }; + } + finally + { + if (lockedPtr != IntPtr.Zero) memMgr.Unlock(cap.hContainer); + if (freeMemory) + { + memMgr.Free(cap.hContainer); + cap.hContainer = IntPtr.Zero; + } + } + } + + public static Range? ReadRange(this ref TW_CAPABILITY cap, IMemoryManager memMgr, bool freeMemory = true) where TValue : struct + { + if (cap.ConType != TWON.RANGE || cap.hContainer == IntPtr.Zero) return null; + + var lockedPtr = memMgr.Lock(cap.hContainer); + + try + { + TWTY itemType; + // Mac has a level of indirection and a different structure (ick)... + if (TWPlatform.IsMacOSX) + { + itemType = (TWTY)Marshal.ReadInt32(lockedPtr); + lockedPtr += 4; + } + else + { + // Windows or the 2.4+ Linux DSM... + itemType = (TWTY)Marshal.ReadInt16(lockedPtr); + lockedPtr += 2; + } + var minValue = ReadTWTYData(lockedPtr, itemType, 0); + lockedPtr += 4; + var maxValue = ReadTWTYData(lockedPtr, itemType, 0); + lockedPtr += 4; + var stepSize = ReadTWTYData(lockedPtr, itemType, 0); + lockedPtr += 4; + var currentValue = ReadTWTYData(lockedPtr, itemType, 0); + lockedPtr += 4; + var defaultValue = ReadTWTYData(lockedPtr, itemType, 0); + lockedPtr += 4; + return new Range + { + MinValue = minValue, + MaxValue = maxValue, + StepSize = stepSize, + CurrentValue = currentValue, + DefaultValue = defaultValue + }; + } + finally + { + if (lockedPtr != IntPtr.Zero) memMgr.Unlock(cap.hContainer); + if (freeMemory) + { + memMgr.Free(cap.hContainer); + cap.hContainer = IntPtr.Zero; + } + } + } + + /// + /// Read the pointer as string. This is for cap's one value string pointer + /// that + /// + /// + /// + /// + /// + public static string? ReadString(this ref TW_CAPABILITY cap, IMemoryManager memMgr, bool freeMemory = true) + { + if (cap.hContainer == IntPtr.Zero) return null; + + var lockedPtr = memMgr.Lock(cap.hContainer); + + try + { + if (cap.ConType == TWON.ONEVALUE) + { + TWTY itemType; + // Mac has a level of indirection and a different structure (ick)... + if (TWPlatform.IsMacOSX) + { + // Crack the container... + var onevalue = MarshalTo(lockedPtr); + itemType = (TWTY)onevalue.ItemType; + lockedPtr += Marshal.SizeOf(onevalue); + } + else + { + // Crack the container... + var onevalue = MarshalTo(lockedPtr); + itemType = onevalue.ItemType; + lockedPtr += Marshal.SizeOf(onevalue); + } + + switch (itemType) + { + case TWTY.STR32: + return MarshalTo(lockedPtr).ToString(); + case TWTY.STR64: + return MarshalTo(lockedPtr).ToString(); + case TWTY.STR128: + return MarshalTo(lockedPtr).ToString(); + case TWTY.STR255: + return MarshalTo(lockedPtr).ToString(); + case TWTY.HANDLE: + // TODO: how to determine the length of this thing??? + // null-terminated and encoded string? + // good chance this ain't right. + using (var stream = new MemoryStream()) + { + byte read = Marshal.ReadByte(lockedPtr); + while (read != 0) + { + stream.WriteByte(read); + read = Marshal.ReadByte(lockedPtr); + lockedPtr += 1; + } + // which one? + //return Encoding.Unicode.GetString(Encoding.Convert(Language.GetEncoding(), Encoding.Unicode, stream.ToArray())); + return Language.GetEncoding().GetString(stream.ToArray()); + } + } + } + } + finally + { + if (lockedPtr != IntPtr.Zero) memMgr.Unlock(cap.hContainer); + if (freeMemory) + { + memMgr.Free(cap.hContainer); + cap.hContainer = IntPtr.Zero; + } + } + return null; + } + + + + /// + /// Read the pointer content as a boxed value specified by , except . + /// + /// A locked pointer to the data pointer. If data is array this is the 0th item. + /// The twain type. + /// Index of the item if pointer is array. + /// + public static object ReadTWTYDataBoxed(this IntPtr intptr, TWTY type, int itemIndex) + { + switch (type) + { + default: + throw new NotSupportedException($"Unsupported item type {type} for reading."); + // TODO: verify if needs to read int32 for small types + case TWTY.HANDLE: + intptr += IntPtr.Size * itemIndex; + return MarshalTo(intptr); + case TWTY.INT8: + intptr += 1 * itemIndex; + return MarshalTo(intptr); + case TWTY.UINT8: + intptr += 1 * itemIndex; + return MarshalTo(intptr); + case TWTY.INT16: + intptr += 2 * itemIndex; + return MarshalTo(intptr); + case TWTY.BOOL: + case TWTY.UINT16: + intptr += 2 * itemIndex; + return MarshalTo(intptr); + case TWTY.INT32: + intptr += 4 * itemIndex; + return MarshalTo(intptr); + case TWTY.UINT32: + intptr += 4 * itemIndex; + return MarshalTo(intptr); + case TWTY.FIX32: + intptr += 4 * itemIndex; + return MarshalTo(intptr); + case TWTY.FRAME: + intptr += 16 * itemIndex; + return MarshalTo(intptr); + case TWTY.STR32: + intptr += TW_STR32.Size * itemIndex; + return MarshalTo(intptr); + case TWTY.STR64: + intptr += TW_STR64.Size * itemIndex; + return MarshalTo(intptr); + case TWTY.STR128: + intptr += TW_STR128.Size * itemIndex; + return MarshalTo(intptr); + case TWTY.STR255: + intptr += TW_STR255.Size * itemIndex; + return MarshalTo(intptr); + } + } + + /// + /// Read the pointer content as a value specified by , except . + /// + /// A locked pointer to the data pointer. If data is array this is the 0th item. + /// The twain type. + /// Index of the item if pointer is array. + /// + public static TValue ReadTWTYData(this IntPtr intptr, TWTY type, int itemIndex) where TValue : struct + { + var isEnum = typeof(TValue).IsEnum; + + switch (type) + { + default: + throw new NotSupportedException($"Unsupported item type {type} for reading."); + // TODO: verify if needs to read int32 for small types + case TWTY.HANDLE: + intptr += IntPtr.Size * itemIndex; + return MarshalTo(intptr); + case TWTY.INT8: + intptr += 1 * itemIndex; + if (isEnum) + { + return NumericToEnum(MarshalTo(intptr)); + } + return MarshalTo(intptr); + case TWTY.UINT8: + intptr += 1 * itemIndex; + if (isEnum) + { + return NumericToEnum(MarshalTo(intptr)); + } + return MarshalTo(intptr); + case TWTY.INT16: + intptr += 2 * itemIndex; + if (isEnum) + { + return NumericToEnum(MarshalTo(intptr)); + } + return MarshalTo(intptr); + case TWTY.BOOL: + case TWTY.UINT16: + intptr += 2 * itemIndex; + if (isEnum) + { + return NumericToEnum(MarshalTo(intptr)); + } + return MarshalTo(intptr); + case TWTY.INT32: + intptr += 4 * itemIndex; + if (isEnum) + { + return NumericToEnum(MarshalTo(intptr)); + } + return MarshalTo(intptr); + case TWTY.UINT32: + intptr += 4 * itemIndex; + if (isEnum) + { + return NumericToEnum(MarshalTo(intptr)); + } + return MarshalTo(intptr); + case TWTY.FIX32: + intptr += 4 * itemIndex; + return MarshalTo(intptr); + case TWTY.FRAME: + intptr += 16 * itemIndex; + return MarshalTo(intptr); + case TWTY.STR32: + intptr += TW_STR32.Size * itemIndex; + return MarshalTo(intptr); + case TWTY.STR64: + intptr += TW_STR64.Size * itemIndex; + return MarshalTo(intptr); + case TWTY.STR128: + intptr += TW_STR128.Size * itemIndex; + return MarshalTo(intptr); + case TWTY.STR255: + intptr += TW_STR255.Size * itemIndex; + return MarshalTo(intptr); + } + } + + static TEnum NumericToEnum(TNumber num) where TEnum : struct + { + // TODO: some caps returns a data type that's not the underlying datatype for the enum + // so foolproof way is to ToString() it and parse it as the enum type. + // this is bad for perf so find better way later + var str = num!.ToString(); + + if (Enum.TryParse(str, out TEnum parsed)) + { + return parsed; + } + return default; + } + } diff --git a/src/NTwain/Data/ValueWriter.cs b/src/NTwain/Data/ValueWriter.cs index 41b5032..d5df025 100644 --- a/src/NTwain/Data/ValueWriter.cs +++ b/src/NTwain/Data/ValueWriter.cs @@ -4,646 +4,645 @@ using System.Diagnostics; using System.Runtime.InteropServices; using System.Text; -namespace NTwain.Data +namespace NTwain.Data; + +/// +/// Contains methods for writing vairous things to pointers. +/// +public static class ValueWriter { /// - /// Contains methods for writing vairous things to pointers. + /// Allocates and copies the string value into a pointer in UTF8 that's null-terminated. /// - public static class ValueWriter + /// + /// + /// Final length to use with the pointer (includes the null). + /// + public static unsafe IntPtr StringToPtrUTF8(this string? value, IMemoryManager memMgr, out uint finalLength) { - /// - /// Allocates and copies the string value into a pointer in UTF8 that's null-terminated. - /// - /// - /// - /// Final length to use with the pointer (includes the null). - /// - public static unsafe IntPtr StringToPtrUTF8(this string? value, IMemoryManager memMgr, out uint finalLength) - { - finalLength = 0; - if (value == null) return IntPtr.Zero; + finalLength = 0; + if (value == null) return IntPtr.Zero; - fixed (char* pInput = value) + fixed (char* pInput = value) + { + var len = Encoding.UTF8.GetByteCount(pInput, value.Length); + finalLength = (uint)len + 1; + var pResult = (byte*)memMgr.Alloc(finalLength); + var bytesWritten = Encoding.UTF8.GetBytes(pInput, value.Length, pResult, len); + Trace.Assert(len == bytesWritten); + pResult[len] = 0; + return (IntPtr)pResult; + } + } + + + + // most of these are modified from the original TWAIN.CsvToCapability() + + /// + /// Creates a with a one-value container. + /// Caller will be responsible for ensuring memory is freed. + /// + /// + /// + /// + /// + /// + public static TW_CAPABILITY CreateOneValueCap(this CAP cap, IMemoryManager memMgr, TValue value) where TValue : struct + { + TW_CAPABILITY twCap = new() { Cap = cap, ConType = TWON.ONEVALUE }; + + IntPtr lockedPtr = IntPtr.Zero; + try + { + //if (twcap.hContainer != IntPtr.Zero) memMgr.Free(ref twcap.hContainer); + + TWTY itemType = GetItemType(); + + // Allocate the container (go for worst case, which is TW_STR255)... + if (TWPlatform.IsMacOSX) { - var len = Encoding.UTF8.GetByteCount(pInput, value.Length); - finalLength = (uint)len + 1; - var pResult = (byte*)memMgr.Alloc(finalLength); - var bytesWritten = Encoding.UTF8.GetBytes(pInput, value.Length, pResult, len); - Trace.Assert(len == bytesWritten); - pResult[len] = 0; - return (IntPtr)pResult; + twCap.hContainer = memMgr.Alloc((uint)(Marshal.SizeOf(default(TW_ONEVALUE_MACOSX)) + Marshal.SizeOf(default(TW_STR255)))); + lockedPtr = memMgr.Lock(twCap.hContainer); + + TW_ONEVALUE_MACOSX twonevaluemacosx = default; + twonevaluemacosx.ItemType = (uint)itemType; + Marshal.StructureToPtr(twonevaluemacosx, lockedPtr, false); + + lockedPtr += Marshal.SizeOf(twonevaluemacosx); + } + else + { + twCap.hContainer = memMgr.Alloc((uint)(Marshal.SizeOf(default(TW_ONEVALUE)) + Marshal.SizeOf(default(TW_STR255)))); + lockedPtr = memMgr.Lock(twCap.hContainer); + + TW_ONEVALUE twonevalue = default; + twonevalue.ItemType = itemType; + Marshal.StructureToPtr(twonevalue, lockedPtr, false); + + lockedPtr += Marshal.SizeOf(twonevalue); + } + + WriteContainerData(lockedPtr, itemType, value, 0); + } + finally + { + if (lockedPtr != IntPtr.Zero) memMgr.Unlock(twCap.hContainer); + } + return twCap; + } + + /// + /// Creates a with multiple values in an array container. + /// Caller will be responsible for ensuring memory is freed. + /// + /// + /// + /// + /// + /// + public static TW_CAPABILITY CreateArrayCap(this CAP cap, IMemoryManager memMgr, IList values) where TValue : struct + { + if (values == null) throw new ArgumentNullException(nameof(values)); + + TW_CAPABILITY twCap = new() { Cap = cap, ConType = TWON.ARRAY }; + + IntPtr lockedPtr = IntPtr.Zero; + try + { + //if (twCap.hContainer != IntPtr.Zero) memMgr.Free(ref twCap.hContainer); + + TWTY itemType = GetItemType(); + + // Allocate the container (go for worst case, which is TW_STR255)... + if (TWPlatform.IsMacOSX) + { + // Allocate... + twCap.hContainer = memMgr.Alloc((uint)(Marshal.SizeOf(default(TW_ARRAY_MACOSX)) + ((values.Count + 1) * Marshal.SizeOf(default(TW_STR255))))); + lockedPtr = memMgr.Lock(twCap.hContainer); + + // Set the meta data... + TW_ARRAY_MACOSX twarraymacosx = default; + twarraymacosx.ItemType = (uint)itemType; + twarraymacosx.NumItems = (uint)values.Count; + Marshal.StructureToPtr(twarraymacosx, lockedPtr, false); + + // Get the pointer to the ItemList... + lockedPtr += Marshal.SizeOf(twarraymacosx); + } + else + { + // Allocate... + twCap.hContainer = memMgr.Alloc((uint)(Marshal.SizeOf(default(TW_ARRAY)) + ((values.Count + 1) * Marshal.SizeOf(default(TW_STR255))))); + lockedPtr = memMgr.Lock(twCap.hContainer); + + // Set the meta data... + TW_ARRAY twarray = default; + twarray.ItemType = itemType; + twarray.NumItems = (uint)values.Count; + Marshal.StructureToPtr(twarray, lockedPtr, false); + + // Get the pointer to the ItemList... + lockedPtr += Marshal.SizeOf(twarray); + } + + // Set the ItemList... + for (var i = 0; i < values.Count; i++) + { + WriteContainerData(lockedPtr, itemType, values[i], i); } } - - - - // most of these are modified from the original TWAIN.CsvToCapability() - - /// - /// Creates a with a one-value container. - /// Caller will be responsible for ensuring memory is freed. - /// - /// - /// - /// - /// - /// - public static TW_CAPABILITY CreateOneValueCap(this CAP cap, IMemoryManager memMgr, TValue value) where TValue : struct + finally { - TW_CAPABILITY twCap = new() { Cap = cap, ConType = TWON.ONEVALUE }; - - IntPtr lockedPtr = IntPtr.Zero; - try - { - //if (twcap.hContainer != IntPtr.Zero) memMgr.Free(ref twcap.hContainer); - - TWTY itemType = GetItemType(); - - // Allocate the container (go for worst case, which is TW_STR255)... - if (TWPlatform.IsMacOSX) - { - twCap.hContainer = memMgr.Alloc((uint)(Marshal.SizeOf(default(TW_ONEVALUE_MACOSX)) + Marshal.SizeOf(default(TW_STR255)))); - lockedPtr = memMgr.Lock(twCap.hContainer); - - TW_ONEVALUE_MACOSX twonevaluemacosx = default; - twonevaluemacosx.ItemType = (uint)itemType; - Marshal.StructureToPtr(twonevaluemacosx, lockedPtr, false); - - lockedPtr += Marshal.SizeOf(twonevaluemacosx); - } - else - { - twCap.hContainer = memMgr.Alloc((uint)(Marshal.SizeOf(default(TW_ONEVALUE)) + Marshal.SizeOf(default(TW_STR255)))); - lockedPtr = memMgr.Lock(twCap.hContainer); - - TW_ONEVALUE twonevalue = default; - twonevalue.ItemType = itemType; - Marshal.StructureToPtr(twonevalue, lockedPtr, false); - - lockedPtr += Marshal.SizeOf(twonevalue); - } - - WriteContainerData(lockedPtr, itemType, value, 0); - } - finally - { - if (lockedPtr != IntPtr.Zero) memMgr.Unlock(twCap.hContainer); - } - return twCap; + if (lockedPtr != IntPtr.Zero) memMgr.Unlock(twCap.hContainer); } + return twCap; + } - /// - /// Creates a with multiple values in an array container. - /// Caller will be responsible for ensuring memory is freed. - /// - /// - /// - /// - /// - /// - public static TW_CAPABILITY CreateArrayCap(this CAP cap, IMemoryManager memMgr, IList values) where TValue : struct + /// + /// Creates a with multiple values in an enum container. + /// Caller will be responsible for ensuring memory is freed. + /// + /// + /// + /// + /// + /// + /// + public static TW_CAPABILITY CreateEnumCap(this CAP cap, IMemoryManager memMgr, Enumeration value) where TValue : struct + { + if (value.Items == null) throw new ArgumentException("No items found in enumeration", nameof(value)); + + TW_CAPABILITY twCap = new() { Cap = cap, ConType = TWON.ENUMERATION }; + + IntPtr lockedPtr = IntPtr.Zero; + try { - if (values == null) throw new ArgumentNullException(nameof(values)); + //if (twCap.hContainer != IntPtr.Zero) memMgr.Free(ref twCap.hContainer); - TW_CAPABILITY twCap = new() { Cap = cap, ConType = TWON.ARRAY }; + TWTY itemType = GetItemType(); - IntPtr lockedPtr = IntPtr.Zero; - try + // Allocate the container (go for worst case, which is TW_STR255)... + if (TWPlatform.IsMacOSX) { - //if (twCap.hContainer != IntPtr.Zero) memMgr.Free(ref twCap.hContainer); + // Allocate... + twCap.hContainer = memMgr.Alloc((uint)(Marshal.SizeOf(default(TW_ENUMERATION_MACOSX)) + ((value.Items.Length + 1) * Marshal.SizeOf(default(TW_STR255))))); + lockedPtr = memMgr.Lock(twCap.hContainer); - TWTY itemType = GetItemType(); + // Set the meta data... + TW_ENUMERATION_MACOSX twenumerationmacosx = default; + twenumerationmacosx.ItemType = (uint)itemType; + twenumerationmacosx.NumItems = (uint)value.Items.Length; + twenumerationmacosx.CurrentIndex = (uint)value.CurrentIndex; + twenumerationmacosx.DefaultIndex = (uint)value.DefaultIndex; + Marshal.StructureToPtr(twenumerationmacosx, lockedPtr, false); - // Allocate the container (go for worst case, which is TW_STR255)... - if (TWPlatform.IsMacOSX) - { - // Allocate... - twCap.hContainer = memMgr.Alloc((uint)(Marshal.SizeOf(default(TW_ARRAY_MACOSX)) + ((values.Count + 1) * Marshal.SizeOf(default(TW_STR255))))); - lockedPtr = memMgr.Lock(twCap.hContainer); - - // Set the meta data... - TW_ARRAY_MACOSX twarraymacosx = default; - twarraymacosx.ItemType = (uint)itemType; - twarraymacosx.NumItems = (uint)values.Count; - Marshal.StructureToPtr(twarraymacosx, lockedPtr, false); - - // Get the pointer to the ItemList... - lockedPtr += Marshal.SizeOf(twarraymacosx); - } - else - { - // Allocate... - twCap.hContainer = memMgr.Alloc((uint)(Marshal.SizeOf(default(TW_ARRAY)) + ((values.Count + 1) * Marshal.SizeOf(default(TW_STR255))))); - lockedPtr = memMgr.Lock(twCap.hContainer); - - // Set the meta data... - TW_ARRAY twarray = default; - twarray.ItemType = itemType; - twarray.NumItems = (uint)values.Count; - Marshal.StructureToPtr(twarray, lockedPtr, false); - - // Get the pointer to the ItemList... - lockedPtr += Marshal.SizeOf(twarray); - } - - // Set the ItemList... - for (var i = 0; i < values.Count; i++) - { - WriteContainerData(lockedPtr, itemType, values[i], i); - } + // Get the pointer to the ItemList... + lockedPtr += Marshal.SizeOf(twenumerationmacosx); } - finally + // Windows or the 2.4+ Linux DSM... + else { - if (lockedPtr != IntPtr.Zero) memMgr.Unlock(twCap.hContainer); + // Allocate... + twCap.hContainer = memMgr.Alloc((uint)(Marshal.SizeOf(default(TW_ENUMERATION)) + ((value.Items.Length + 1) * Marshal.SizeOf(default(TW_STR255))))); + lockedPtr = memMgr.Lock(twCap.hContainer); + + // Set the meta data... + TW_ENUMERATION twenumeration = default; + twenumeration.ItemType = itemType; + twenumeration.NumItems = (uint)value.Items.Length; + twenumeration.CurrentIndex = (uint)value.CurrentIndex; + twenumeration.DefaultIndex = (uint)value.CurrentIndex; + Marshal.StructureToPtr(twenumeration, lockedPtr, false); + + // Get the pointer to the ItemList... + lockedPtr += Marshal.SizeOf(twenumeration); + } + // The -2.3 Linux DSM... + //else + //{ + // // Allocate... + // twCap.hContainer = memMgr.Alloc((uint)(Marshal.SizeOf(default(TW_ENUMERATION_LINUX64)) + ((value.Items.Length + 1) * Marshal.SizeOf(default(TW_STR255))))); + // lockedPtr = memMgr.Lock(twCap.hContainer); + + // // Set the meta data... + // TW_ENUMERATION_LINUX64 twenumerationlinux64 = default; + // twenumerationlinux64.ItemType = itemType; + // twenumerationlinux64.NumItems = (ulong)value.Items.Length; + // twenumerationlinux64.CurrentIndex = (ulong)value.CurrentIndex; + // twenumerationlinux64.DefaultIndex = (ulong)value.CurrentIndex; + // Marshal.StructureToPtr(twenumerationlinux64, lockedPtr, false); + + // // Get the pointer to the ItemList... + // lockedPtr += Marshal.SizeOf(twenumerationlinux64); + //} + + // Set the ItemList... + for (var i = 0; i < value.Items.Length; i++) + { + WriteContainerData(lockedPtr, itemType, value.Items[i], i); } - return twCap; } - - /// - /// Creates a with multiple values in an enum container. - /// Caller will be responsible for ensuring memory is freed. - /// - /// - /// - /// - /// - /// - /// - public static TW_CAPABILITY CreateEnumCap(this CAP cap, IMemoryManager memMgr, Enumeration value) where TValue : struct + finally { - if (value.Items == null) throw new ArgumentException("No items found in enumeration", nameof(value)); + if (lockedPtr != IntPtr.Zero) memMgr.Unlock(twCap.hContainer); + } + return twCap; + } - TW_CAPABILITY twCap = new() { Cap = cap, ConType = TWON.ENUMERATION }; + /// + /// Creates a with multiple values in a range container. + /// Caller will be responsible for ensuring memory is freed. + /// + /// + /// + /// + /// + /// + public static TW_CAPABILITY CreateRangeCap(this CAP cap, IMemoryManager memMgr, Range value) where TValue : struct + { + TW_CAPABILITY twCap = new() { Cap = cap, ConType = TWON.RANGE }; - IntPtr lockedPtr = IntPtr.Zero; - try + IntPtr lockedPtr = IntPtr.Zero; + try + { + //if (twCap.hContainer != IntPtr.Zero) memMgr.Free(ref twCap.hContainer); + + TWTY itemType = GetItemType(); + + // Allocate the container (go for worst case, which is TW_STR255)... + if (TWPlatform.IsMacOSX) { - //if (twCap.hContainer != IntPtr.Zero) memMgr.Free(ref twCap.hContainer); + // Allocate... + twCap.hContainer = memMgr.Alloc((uint)(Marshal.SizeOf(default(TW_RANGE_MACOSX)))); + lockedPtr = memMgr.Lock(twCap.hContainer); + } + // Windows or the 2.4+ Linux DSM... + else + { + // Allocate... + twCap.hContainer = memMgr.Alloc((uint)(Marshal.SizeOf(default(TW_RANGE)))); + lockedPtr = memMgr.Lock(twCap.hContainer); + } + //// The -2.3 Linux DSM... + //else + //{ + // // Allocate... + // twCap.hContainer = memMgr.Alloc((uint)(Marshal.SizeOf(default(TW_RANGE_LINUX64)))); + // lockedPtr = memMgr.Lock(twCap.hContainer); + //} - TWTY itemType = GetItemType(); + // Set the Item... + WriteRangeValues(lockedPtr, itemType, value); + } + finally + { + if (lockedPtr != IntPtr.Zero) memMgr.Unlock(twCap.hContainer); + } + return twCap; + } - // Allocate the container (go for worst case, which is TW_STR255)... + static void WriteRangeValues(IntPtr lockedPtr, TWTY itemType, Range value) where TValue : struct + { + // TODO: reduce this later + + TW_RANGE twrange = default; + TW_RANGE_MACOSX twrangemacosx = default; + //TW_RANGE_LINUX64 twrangelinux64 = default; + + switch (itemType) + { + default: + throw new NotSupportedException($"{itemType} is not supported for range."); + case TWTY.INT8: if (TWPlatform.IsMacOSX) { - // Allocate... - twCap.hContainer = memMgr.Alloc((uint)(Marshal.SizeOf(default(TW_ENUMERATION_MACOSX)) + ((value.Items.Length + 1) * Marshal.SizeOf(default(TW_STR255))))); - lockedPtr = memMgr.Lock(twCap.hContainer); - - // Set the meta data... - TW_ENUMERATION_MACOSX twenumerationmacosx = default; - twenumerationmacosx.ItemType = (uint)itemType; - twenumerationmacosx.NumItems = (uint)value.Items.Length; - twenumerationmacosx.CurrentIndex = (uint)value.CurrentIndex; - twenumerationmacosx.DefaultIndex = (uint)value.DefaultIndex; - Marshal.StructureToPtr(twenumerationmacosx, lockedPtr, false); - - // Get the pointer to the ItemList... - lockedPtr += Marshal.SizeOf(twenumerationmacosx); + twrangemacosx.ItemType = (uint)itemType; + twrangemacosx.MinValue = (uint)Convert.ToSByte(value.MinValue); + twrangemacosx.MaxValue = (uint)Convert.ToSByte(value.MaxValue); + twrangemacosx.StepSize = (uint)Convert.ToSByte(value.StepSize); + twrangemacosx.DefaultValue = (uint)Convert.ToSByte(value.DefaultValue); + twrangemacosx.CurrentValue = (uint)Convert.ToSByte(value.CurrentValue); + Marshal.StructureToPtr(twrangemacosx, lockedPtr, false); } - // Windows or the 2.4+ Linux DSM... - else + else //if ((twain.m_linuxdsm == TWAIN.LinuxDsm.Unknown) || (twain.m_linuxdsm == TWAIN.LinuxDsm.IsLatestDsm)) { - // Allocate... - twCap.hContainer = memMgr.Alloc((uint)(Marshal.SizeOf(default(TW_ENUMERATION)) + ((value.Items.Length + 1) * Marshal.SizeOf(default(TW_STR255))))); - lockedPtr = memMgr.Lock(twCap.hContainer); - - // Set the meta data... - TW_ENUMERATION twenumeration = default; - twenumeration.ItemType = itemType; - twenumeration.NumItems = (uint)value.Items.Length; - twenumeration.CurrentIndex = (uint)value.CurrentIndex; - twenumeration.DefaultIndex = (uint)value.CurrentIndex; - Marshal.StructureToPtr(twenumeration, lockedPtr, false); - - // Get the pointer to the ItemList... - lockedPtr += Marshal.SizeOf(twenumeration); + twrange.ItemType = itemType; + twrange.MinValue = (uint)Convert.ToSByte(value.MinValue); + twrange.MaxValue = (uint)Convert.ToSByte(value.MaxValue); + twrange.StepSize = (uint)Convert.ToSByte(value.StepSize); + twrange.DefaultValue = (uint)Convert.ToSByte(value.DefaultValue); + twrange.CurrentValue = (uint)Convert.ToSByte(value.CurrentValue); + Marshal.StructureToPtr(twrange, lockedPtr, false); } - // The -2.3 Linux DSM... //else //{ - // // Allocate... - // twCap.hContainer = memMgr.Alloc((uint)(Marshal.SizeOf(default(TW_ENUMERATION_LINUX64)) + ((value.Items.Length + 1) * Marshal.SizeOf(default(TW_STR255))))); - // lockedPtr = memMgr.Lock(twCap.hContainer); - - // // Set the meta data... - // TW_ENUMERATION_LINUX64 twenumerationlinux64 = default; - // twenumerationlinux64.ItemType = itemType; - // twenumerationlinux64.NumItems = (ulong)value.Items.Length; - // twenumerationlinux64.CurrentIndex = (ulong)value.CurrentIndex; - // twenumerationlinux64.DefaultIndex = (ulong)value.CurrentIndex; - // Marshal.StructureToPtr(twenumerationlinux64, lockedPtr, false); - - // // Get the pointer to the ItemList... - // lockedPtr += Marshal.SizeOf(twenumerationlinux64); + // twrangelinux64.ItemType = itemType; + // twrangelinux64.MinValue = (uint)Convert.ToSByte(value.MinValue); + // twrangelinux64.MaxValue = (uint)Convert.ToSByte(value.MaxValue); + // twrangelinux64.StepSize = (uint)Convert.ToSByte(value.StepSize); + // twrangelinux64.DefaultValue = (uint)Convert.ToSByte(value.DefaultValue); + // twrangelinux64.CurrentValue = (uint)Convert.ToSByte(value.CurrentValue); + // Marshal.StructureToPtr(twrangelinux64, lockedPtr, false); //} - - // Set the ItemList... - for (var i = 0; i < value.Items.Length; i++) - { - WriteContainerData(lockedPtr, itemType, value.Items[i], i); - } - } - finally - { - if (lockedPtr != IntPtr.Zero) memMgr.Unlock(twCap.hContainer); - } - return twCap; - } - - /// - /// Creates a with multiple values in a range container. - /// Caller will be responsible for ensuring memory is freed. - /// - /// - /// - /// - /// - /// - public static TW_CAPABILITY CreateRangeCap(this CAP cap, IMemoryManager memMgr, Range value) where TValue : struct - { - TW_CAPABILITY twCap = new() { Cap = cap, ConType = TWON.RANGE }; - - IntPtr lockedPtr = IntPtr.Zero; - try - { - //if (twCap.hContainer != IntPtr.Zero) memMgr.Free(ref twCap.hContainer); - - TWTY itemType = GetItemType(); - - // Allocate the container (go for worst case, which is TW_STR255)... + break; + case TWTY.UINT8: if (TWPlatform.IsMacOSX) { - // Allocate... - twCap.hContainer = memMgr.Alloc((uint)(Marshal.SizeOf(default(TW_RANGE_MACOSX)))); - lockedPtr = memMgr.Lock(twCap.hContainer); + twrangemacosx.ItemType = (uint)itemType; + twrangemacosx.MinValue = Convert.ToByte(value.MinValue); + twrangemacosx.MaxValue = Convert.ToByte(value.MaxValue); + twrangemacosx.StepSize = Convert.ToByte(value.StepSize); + twrangemacosx.DefaultValue = Convert.ToByte(value.DefaultValue); + twrangemacosx.CurrentValue = Convert.ToByte(value.CurrentValue); + Marshal.StructureToPtr(twrangemacosx, lockedPtr, false); } - // Windows or the 2.4+ Linux DSM... - else + else //if ((twain.m_linuxdsm == TWAIN.LinuxDsm.Unknown) || (twain.m_linuxdsm == TWAIN.LinuxDsm.IsLatestDsm)) { - // Allocate... - twCap.hContainer = memMgr.Alloc((uint)(Marshal.SizeOf(default(TW_RANGE)))); - lockedPtr = memMgr.Lock(twCap.hContainer); + twrange.ItemType = itemType; + twrange.MinValue = Convert.ToByte(value.MinValue); + twrange.MaxValue = Convert.ToByte(value.MaxValue); + twrange.StepSize = Convert.ToByte(value.StepSize); + twrange.DefaultValue = Convert.ToByte(value.DefaultValue); + twrange.CurrentValue = Convert.ToByte(value.CurrentValue); + Marshal.StructureToPtr(twrange, lockedPtr, false); } - //// The -2.3 Linux DSM... //else //{ - // // Allocate... - // twCap.hContainer = memMgr.Alloc((uint)(Marshal.SizeOf(default(TW_RANGE_LINUX64)))); - // lockedPtr = memMgr.Lock(twCap.hContainer); + // twrangelinux64.ItemType = itemType; + // twrangelinux64.MinValue = Convert.ToByte(value.MinValue); + // twrangelinux64.MaxValue = Convert.ToByte(value.MaxValue); + // twrangelinux64.StepSize = Convert.ToByte(value.StepSize); + // twrangelinux64.DefaultValue = Convert.ToByte(value.DefaultValue); + // twrangelinux64.CurrentValue = Convert.ToByte(value.CurrentValue); + // Marshal.StructureToPtr(twrangelinux64, lockedPtr, false); //} + break; + case TWTY.INT16: + if (TWPlatform.IsMacOSX) + { + twrangemacosx.ItemType = (uint)itemType; + twrangemacosx.MinValue = (uint)Convert.ToInt16(value.MinValue); + twrangemacosx.MaxValue = (uint)Convert.ToInt16(value.MaxValue); + twrangemacosx.StepSize = (uint)Convert.ToInt16(value.StepSize); + twrangemacosx.DefaultValue = (uint)Convert.ToInt16(value.DefaultValue); + twrangemacosx.CurrentValue = (uint)Convert.ToInt16(value.CurrentValue); + Marshal.StructureToPtr(twrangemacosx, lockedPtr, false); + } + else // if ((twain.m_linuxdsm == TWAIN.LinuxDsm.Unknown) || (twain.m_linuxdsm == TWAIN.LinuxDsm.IsLatestDsm)) + { + twrange.ItemType = itemType; + twrange.MinValue = (uint)Convert.ToInt16(value.MinValue); + twrange.MaxValue = (uint)Convert.ToInt16(value.MaxValue); + twrange.StepSize = (uint)Convert.ToInt16(value.StepSize); + twrange.DefaultValue = (uint)Convert.ToInt16(value.DefaultValue); + twrange.CurrentValue = (uint)Convert.ToInt16(value.CurrentValue); + Marshal.StructureToPtr(twrange, lockedPtr, false); + } + //else + //{ + // twrangelinux64.ItemType = itemType; + // twrangelinux64.MinValue = (uint)Convert.ToInt16(value.MinValue); + // twrangelinux64.MaxValue = (uint)Convert.ToInt16(value.MaxValue); + // twrangelinux64.StepSize = (uint)Convert.ToInt16(value.StepSize); + // twrangelinux64.DefaultValue = (uint)Convert.ToInt16(value.DefaultValue); + // twrangelinux64.CurrentValue = (uint)Convert.ToInt16(value.CurrentValue); + // Marshal.StructureToPtr(twrangelinux64, lockedPtr, false); + //} + break; + case TWTY.BOOL: + case TWTY.UINT16: + if (TWPlatform.IsMacOSX) + { + twrangemacosx.ItemType = (uint)itemType; + twrangemacosx.MinValue = Convert.ToUInt16(value.MinValue); + twrangemacosx.MaxValue = Convert.ToUInt16(value.MaxValue); + twrangemacosx.StepSize = Convert.ToUInt16(value.StepSize); + twrangemacosx.DefaultValue = Convert.ToUInt16(value.DefaultValue); + twrangemacosx.CurrentValue = Convert.ToUInt16(value.CurrentValue); + Marshal.StructureToPtr(twrangemacosx, lockedPtr, false); + } + else //if ((twain.m_linuxdsm == TWAIN.LinuxDsm.Unknown) || (twain.m_linuxdsm == TWAIN.LinuxDsm.IsLatestDsm)) + { + twrange.ItemType = itemType; + twrange.MinValue = Convert.ToUInt16(value.MinValue); + twrange.MaxValue = Convert.ToUInt16(value.MaxValue); + twrange.StepSize = Convert.ToUInt16(value.StepSize); + twrange.DefaultValue = Convert.ToUInt16(value.DefaultValue); + twrange.CurrentValue = Convert.ToUInt16(value.CurrentValue); + Marshal.StructureToPtr(twrange, lockedPtr, false); + } + //else + //{ + // twrangelinux64.ItemType = itemType; + // twrangelinux64.MinValue = Convert.ToUInt16(value.MinValue); + // twrangelinux64.MaxValue = Convert.ToUInt16(value.MaxValue); + // twrangelinux64.StepSize = Convert.ToUInt16(value.StepSize); + // twrangelinux64.DefaultValue = Convert.ToUInt16(value.DefaultValue); + // twrangelinux64.CurrentValue = Convert.ToUInt16(value.CurrentValue); + // Marshal.StructureToPtr(twrangelinux64, lockedPtr, false); + //} + break; + case TWTY.INT32: + if (TWPlatform.IsMacOSX) + { + twrangemacosx.ItemType = (uint)itemType; + twrangemacosx.MinValue = (uint)Convert.ToInt32(value.MinValue); + twrangemacosx.MaxValue = (uint)Convert.ToInt32(value.MaxValue); + twrangemacosx.StepSize = (uint)Convert.ToInt32(value.StepSize); + twrangemacosx.DefaultValue = (uint)Convert.ToInt32(value.DefaultValue); + twrangemacosx.CurrentValue = (uint)Convert.ToInt32(value.CurrentValue); + Marshal.StructureToPtr(twrangemacosx, lockedPtr, false); + } + else //if ((twain.m_linuxdsm == TWAIN.LinuxDsm.Unknown) || (twain.m_linuxdsm == TWAIN.LinuxDsm.IsLatestDsm)) + { + twrange.ItemType = itemType; + twrange.MinValue = (uint)Convert.ToInt32(value.MinValue); + twrange.MaxValue = (uint)Convert.ToInt32(value.MaxValue); + twrange.StepSize = (uint)Convert.ToInt32(value.StepSize); + twrange.DefaultValue = (uint)Convert.ToInt32(value.DefaultValue); + twrange.CurrentValue = (uint)Convert.ToInt32(value.CurrentValue); + Marshal.StructureToPtr(twrange, lockedPtr, false); + } + //else + //{ + // twrangelinux64.ItemType = itemType; + // twrangelinux64.MinValue = (uint)Convert.ToInt32(value.MinValue); + // twrangelinux64.MaxValue = (uint)Convert.ToInt32(value.MaxValue); + // twrangelinux64.StepSize = (uint)Convert.ToInt32(value.StepSize); + // twrangelinux64.DefaultValue = (uint)Convert.ToInt32(value.DefaultValue); + // twrangelinux64.CurrentValue = (uint)Convert.ToInt32(value.CurrentValue); + // Marshal.StructureToPtr(twrangelinux64, lockedPtr, false); + //} + break; + case TWTY.UINT32: + if (TWPlatform.IsMacOSX) + { + twrangemacosx.ItemType = (uint)itemType; + twrangemacosx.MinValue = Convert.ToUInt32(value.MinValue); + twrangemacosx.MaxValue = Convert.ToUInt32(value.MaxValue); + twrangemacosx.StepSize = Convert.ToUInt32(value.StepSize); + twrangemacosx.DefaultValue = Convert.ToUInt32(value.DefaultValue); + twrangemacosx.CurrentValue = Convert.ToUInt32(value.CurrentValue); + Marshal.StructureToPtr(twrangemacosx, lockedPtr, false); + } + else //if ((twain.m_linuxdsm == TWAIN.LinuxDsm.Unknown) || (twain.m_linuxdsm == TWAIN.LinuxDsm.IsLatestDsm)) + { + twrange.ItemType = itemType; + twrange.MinValue = Convert.ToUInt32(value.MinValue); + twrange.MaxValue = Convert.ToUInt32(value.MaxValue); + twrange.StepSize = Convert.ToUInt32(value.StepSize); + twrange.DefaultValue = Convert.ToUInt32(value.DefaultValue); + twrange.CurrentValue = Convert.ToUInt32(value.CurrentValue); + Marshal.StructureToPtr(twrange, lockedPtr, false); + } + //else + //{ + // twrangelinux64.ItemType = itemType; + // twrangelinux64.MinValue = Convert.ToUInt32(value.MinValue); + // twrangelinux64.MaxValue = Convert.ToUInt32(value.MaxValue); + // twrangelinux64.StepSize = Convert.ToUInt32(value.StepSize); + // twrangelinux64.DefaultValue = Convert.ToUInt32(value.DefaultValue); + // twrangelinux64.CurrentValue = Convert.ToUInt32(value.CurrentValue); + // Marshal.StructureToPtr(twrangelinux64, lockedPtr, false); + //} + break; + case TWTY.FIX32: + double min = Convert.ToDouble(value.MinValue); + double max = Convert.ToDouble(value.MaxValue); + double step = Convert.ToDouble(value.StepSize); + double def = Convert.ToDouble(value.DefaultValue); + double current = Convert.ToDouble(value.CurrentValue); + if (TWPlatform.IsMacOSX) + { + TW_RANGE_FIX32_MACOSX twrangefix32macosx = default; + twrangefix32macosx.ItemType = (uint)itemType; + twrangefix32macosx.MinValue = new TW_FIX32(min); + twrangefix32macosx.MaxValue = new TW_FIX32(max); + twrangefix32macosx.StepSize = new TW_FIX32(step); + twrangefix32macosx.DefaultValue = new TW_FIX32(def); + twrangefix32macosx.CurrentValue = new TW_FIX32(current); + Marshal.StructureToPtr(twrangefix32macosx, lockedPtr, false); + } + else + { + TW_RANGE_FIX32 twrangefix32 = default; + twrangefix32.ItemType = itemType; + twrangefix32.MinValue = new TW_FIX32(min); + twrangefix32.MaxValue = new TW_FIX32(max); + twrangefix32.StepSize = new TW_FIX32(step); + twrangefix32.DefaultValue = new TW_FIX32(def); + twrangefix32.CurrentValue = new TW_FIX32(current); + Marshal.StructureToPtr(twrangefix32, lockedPtr, false); + } + break; + } + } - // Set the Item... - WriteRangeValues(lockedPtr, itemType, value); - } - finally - { - if (lockedPtr != IntPtr.Zero) memMgr.Unlock(twCap.hContainer); - } - return twCap; + static TWTY GetItemType() + { + var type = typeof(TValue); + if (type == typeof(TW_BOOL)) return TWTY.BOOL; + if (type == typeof(TW_FIX32)) return TWTY.FIX32; + if (type == typeof(TW_STR32)) return TWTY.STR32; + if (type == typeof(TW_STR64)) return TWTY.STR64; + if (type == typeof(TW_STR128)) return TWTY.STR128; + if (type == typeof(TW_STR255)) return TWTY.STR255; + if (type == typeof(TW_FRAME)) return TWTY.FRAME; + if (type == typeof(IntPtr)) return TWTY.HANDLE; + if (type == typeof(UIntPtr)) return TWTY.HANDLE; + + if (type.IsEnum) + { + type = type.GetEnumUnderlyingType(); } - static void WriteRangeValues(IntPtr lockedPtr, TWTY itemType, Range value) where TValue : struct + if (type == typeof(ushort)) return TWTY.UINT16; + if (type == typeof(short)) return TWTY.INT16; + if (type == typeof(uint)) return TWTY.UINT32; + if (type == typeof(int)) return TWTY.INT32; + if (type == typeof(byte)) return TWTY.UINT8; + if (type == typeof(sbyte)) return TWTY.INT8; + + throw new NotSupportedException($"{type.Name} is not supported for writing."); + } + + /// + /// Writes single piece of value to the container pointer. + /// + /// + /// A locked pointer to the container's data pointer. If data is array this is the 0th item. + /// The twain type. + /// + /// Index of the item if pointer is array. + static void WriteContainerData(IntPtr intptr, TWTY type, TValue value, int itemIndex) where TValue : struct + { + switch (type) { - // TODO: reduce this later - - TW_RANGE twrange = default; - TW_RANGE_MACOSX twrangemacosx = default; - //TW_RANGE_LINUX64 twrangelinux64 = default; - - switch (itemType) - { - default: - throw new NotSupportedException($"{itemType} is not supported for range."); - case TWTY.INT8: - if (TWPlatform.IsMacOSX) - { - twrangemacosx.ItemType = (uint)itemType; - twrangemacosx.MinValue = (uint)Convert.ToSByte(value.MinValue); - twrangemacosx.MaxValue = (uint)Convert.ToSByte(value.MaxValue); - twrangemacosx.StepSize = (uint)Convert.ToSByte(value.StepSize); - twrangemacosx.DefaultValue = (uint)Convert.ToSByte(value.DefaultValue); - twrangemacosx.CurrentValue = (uint)Convert.ToSByte(value.CurrentValue); - Marshal.StructureToPtr(twrangemacosx, lockedPtr, false); - } - else //if ((twain.m_linuxdsm == TWAIN.LinuxDsm.Unknown) || (twain.m_linuxdsm == TWAIN.LinuxDsm.IsLatestDsm)) - { - twrange.ItemType = itemType; - twrange.MinValue = (uint)Convert.ToSByte(value.MinValue); - twrange.MaxValue = (uint)Convert.ToSByte(value.MaxValue); - twrange.StepSize = (uint)Convert.ToSByte(value.StepSize); - twrange.DefaultValue = (uint)Convert.ToSByte(value.DefaultValue); - twrange.CurrentValue = (uint)Convert.ToSByte(value.CurrentValue); - Marshal.StructureToPtr(twrange, lockedPtr, false); - } - //else - //{ - // twrangelinux64.ItemType = itemType; - // twrangelinux64.MinValue = (uint)Convert.ToSByte(value.MinValue); - // twrangelinux64.MaxValue = (uint)Convert.ToSByte(value.MaxValue); - // twrangelinux64.StepSize = (uint)Convert.ToSByte(value.StepSize); - // twrangelinux64.DefaultValue = (uint)Convert.ToSByte(value.DefaultValue); - // twrangelinux64.CurrentValue = (uint)Convert.ToSByte(value.CurrentValue); - // Marshal.StructureToPtr(twrangelinux64, lockedPtr, false); - //} - break; - case TWTY.UINT8: - if (TWPlatform.IsMacOSX) - { - twrangemacosx.ItemType = (uint)itemType; - twrangemacosx.MinValue = Convert.ToByte(value.MinValue); - twrangemacosx.MaxValue = Convert.ToByte(value.MaxValue); - twrangemacosx.StepSize = Convert.ToByte(value.StepSize); - twrangemacosx.DefaultValue = Convert.ToByte(value.DefaultValue); - twrangemacosx.CurrentValue = Convert.ToByte(value.CurrentValue); - Marshal.StructureToPtr(twrangemacosx, lockedPtr, false); - } - else //if ((twain.m_linuxdsm == TWAIN.LinuxDsm.Unknown) || (twain.m_linuxdsm == TWAIN.LinuxDsm.IsLatestDsm)) - { - twrange.ItemType = itemType; - twrange.MinValue = Convert.ToByte(value.MinValue); - twrange.MaxValue = Convert.ToByte(value.MaxValue); - twrange.StepSize = Convert.ToByte(value.StepSize); - twrange.DefaultValue = Convert.ToByte(value.DefaultValue); - twrange.CurrentValue = Convert.ToByte(value.CurrentValue); - Marshal.StructureToPtr(twrange, lockedPtr, false); - } - //else - //{ - // twrangelinux64.ItemType = itemType; - // twrangelinux64.MinValue = Convert.ToByte(value.MinValue); - // twrangelinux64.MaxValue = Convert.ToByte(value.MaxValue); - // twrangelinux64.StepSize = Convert.ToByte(value.StepSize); - // twrangelinux64.DefaultValue = Convert.ToByte(value.DefaultValue); - // twrangelinux64.CurrentValue = Convert.ToByte(value.CurrentValue); - // Marshal.StructureToPtr(twrangelinux64, lockedPtr, false); - //} - break; - case TWTY.INT16: - if (TWPlatform.IsMacOSX) - { - twrangemacosx.ItemType = (uint)itemType; - twrangemacosx.MinValue = (uint)Convert.ToInt16(value.MinValue); - twrangemacosx.MaxValue = (uint)Convert.ToInt16(value.MaxValue); - twrangemacosx.StepSize = (uint)Convert.ToInt16(value.StepSize); - twrangemacosx.DefaultValue = (uint)Convert.ToInt16(value.DefaultValue); - twrangemacosx.CurrentValue = (uint)Convert.ToInt16(value.CurrentValue); - Marshal.StructureToPtr(twrangemacosx, lockedPtr, false); - } - else // if ((twain.m_linuxdsm == TWAIN.LinuxDsm.Unknown) || (twain.m_linuxdsm == TWAIN.LinuxDsm.IsLatestDsm)) - { - twrange.ItemType = itemType; - twrange.MinValue = (uint)Convert.ToInt16(value.MinValue); - twrange.MaxValue = (uint)Convert.ToInt16(value.MaxValue); - twrange.StepSize = (uint)Convert.ToInt16(value.StepSize); - twrange.DefaultValue = (uint)Convert.ToInt16(value.DefaultValue); - twrange.CurrentValue = (uint)Convert.ToInt16(value.CurrentValue); - Marshal.StructureToPtr(twrange, lockedPtr, false); - } - //else - //{ - // twrangelinux64.ItemType = itemType; - // twrangelinux64.MinValue = (uint)Convert.ToInt16(value.MinValue); - // twrangelinux64.MaxValue = (uint)Convert.ToInt16(value.MaxValue); - // twrangelinux64.StepSize = (uint)Convert.ToInt16(value.StepSize); - // twrangelinux64.DefaultValue = (uint)Convert.ToInt16(value.DefaultValue); - // twrangelinux64.CurrentValue = (uint)Convert.ToInt16(value.CurrentValue); - // Marshal.StructureToPtr(twrangelinux64, lockedPtr, false); - //} - break; - case TWTY.BOOL: - case TWTY.UINT16: - if (TWPlatform.IsMacOSX) - { - twrangemacosx.ItemType = (uint)itemType; - twrangemacosx.MinValue = Convert.ToUInt16(value.MinValue); - twrangemacosx.MaxValue = Convert.ToUInt16(value.MaxValue); - twrangemacosx.StepSize = Convert.ToUInt16(value.StepSize); - twrangemacosx.DefaultValue = Convert.ToUInt16(value.DefaultValue); - twrangemacosx.CurrentValue = Convert.ToUInt16(value.CurrentValue); - Marshal.StructureToPtr(twrangemacosx, lockedPtr, false); - } - else //if ((twain.m_linuxdsm == TWAIN.LinuxDsm.Unknown) || (twain.m_linuxdsm == TWAIN.LinuxDsm.IsLatestDsm)) - { - twrange.ItemType = itemType; - twrange.MinValue = Convert.ToUInt16(value.MinValue); - twrange.MaxValue = Convert.ToUInt16(value.MaxValue); - twrange.StepSize = Convert.ToUInt16(value.StepSize); - twrange.DefaultValue = Convert.ToUInt16(value.DefaultValue); - twrange.CurrentValue = Convert.ToUInt16(value.CurrentValue); - Marshal.StructureToPtr(twrange, lockedPtr, false); - } - //else - //{ - // twrangelinux64.ItemType = itemType; - // twrangelinux64.MinValue = Convert.ToUInt16(value.MinValue); - // twrangelinux64.MaxValue = Convert.ToUInt16(value.MaxValue); - // twrangelinux64.StepSize = Convert.ToUInt16(value.StepSize); - // twrangelinux64.DefaultValue = Convert.ToUInt16(value.DefaultValue); - // twrangelinux64.CurrentValue = Convert.ToUInt16(value.CurrentValue); - // Marshal.StructureToPtr(twrangelinux64, lockedPtr, false); - //} - break; - case TWTY.INT32: - if (TWPlatform.IsMacOSX) - { - twrangemacosx.ItemType = (uint)itemType; - twrangemacosx.MinValue = (uint)Convert.ToInt32(value.MinValue); - twrangemacosx.MaxValue = (uint)Convert.ToInt32(value.MaxValue); - twrangemacosx.StepSize = (uint)Convert.ToInt32(value.StepSize); - twrangemacosx.DefaultValue = (uint)Convert.ToInt32(value.DefaultValue); - twrangemacosx.CurrentValue = (uint)Convert.ToInt32(value.CurrentValue); - Marshal.StructureToPtr(twrangemacosx, lockedPtr, false); - } - else //if ((twain.m_linuxdsm == TWAIN.LinuxDsm.Unknown) || (twain.m_linuxdsm == TWAIN.LinuxDsm.IsLatestDsm)) - { - twrange.ItemType = itemType; - twrange.MinValue = (uint)Convert.ToInt32(value.MinValue); - twrange.MaxValue = (uint)Convert.ToInt32(value.MaxValue); - twrange.StepSize = (uint)Convert.ToInt32(value.StepSize); - twrange.DefaultValue = (uint)Convert.ToInt32(value.DefaultValue); - twrange.CurrentValue = (uint)Convert.ToInt32(value.CurrentValue); - Marshal.StructureToPtr(twrange, lockedPtr, false); - } - //else - //{ - // twrangelinux64.ItemType = itemType; - // twrangelinux64.MinValue = (uint)Convert.ToInt32(value.MinValue); - // twrangelinux64.MaxValue = (uint)Convert.ToInt32(value.MaxValue); - // twrangelinux64.StepSize = (uint)Convert.ToInt32(value.StepSize); - // twrangelinux64.DefaultValue = (uint)Convert.ToInt32(value.DefaultValue); - // twrangelinux64.CurrentValue = (uint)Convert.ToInt32(value.CurrentValue); - // Marshal.StructureToPtr(twrangelinux64, lockedPtr, false); - //} - break; - case TWTY.UINT32: - if (TWPlatform.IsMacOSX) - { - twrangemacosx.ItemType = (uint)itemType; - twrangemacosx.MinValue = Convert.ToUInt32(value.MinValue); - twrangemacosx.MaxValue = Convert.ToUInt32(value.MaxValue); - twrangemacosx.StepSize = Convert.ToUInt32(value.StepSize); - twrangemacosx.DefaultValue = Convert.ToUInt32(value.DefaultValue); - twrangemacosx.CurrentValue = Convert.ToUInt32(value.CurrentValue); - Marshal.StructureToPtr(twrangemacosx, lockedPtr, false); - } - else //if ((twain.m_linuxdsm == TWAIN.LinuxDsm.Unknown) || (twain.m_linuxdsm == TWAIN.LinuxDsm.IsLatestDsm)) - { - twrange.ItemType = itemType; - twrange.MinValue = Convert.ToUInt32(value.MinValue); - twrange.MaxValue = Convert.ToUInt32(value.MaxValue); - twrange.StepSize = Convert.ToUInt32(value.StepSize); - twrange.DefaultValue = Convert.ToUInt32(value.DefaultValue); - twrange.CurrentValue = Convert.ToUInt32(value.CurrentValue); - Marshal.StructureToPtr(twrange, lockedPtr, false); - } - //else - //{ - // twrangelinux64.ItemType = itemType; - // twrangelinux64.MinValue = Convert.ToUInt32(value.MinValue); - // twrangelinux64.MaxValue = Convert.ToUInt32(value.MaxValue); - // twrangelinux64.StepSize = Convert.ToUInt32(value.StepSize); - // twrangelinux64.DefaultValue = Convert.ToUInt32(value.DefaultValue); - // twrangelinux64.CurrentValue = Convert.ToUInt32(value.CurrentValue); - // Marshal.StructureToPtr(twrangelinux64, lockedPtr, false); - //} - break; - case TWTY.FIX32: - double min = Convert.ToDouble(value.MinValue); - double max = Convert.ToDouble(value.MaxValue); - double step = Convert.ToDouble(value.StepSize); - double def = Convert.ToDouble(value.DefaultValue); - double current = Convert.ToDouble(value.CurrentValue); - if (TWPlatform.IsMacOSX) - { - TW_RANGE_FIX32_MACOSX twrangefix32macosx = default; - twrangefix32macosx.ItemType = (uint)itemType; - twrangefix32macosx.MinValue = new TW_FIX32(min); - twrangefix32macosx.MaxValue = new TW_FIX32(max); - twrangefix32macosx.StepSize = new TW_FIX32(step); - twrangefix32macosx.DefaultValue = new TW_FIX32(def); - twrangefix32macosx.CurrentValue = new TW_FIX32(current); - Marshal.StructureToPtr(twrangefix32macosx, lockedPtr, false); - } - else - { - TW_RANGE_FIX32 twrangefix32 = default; - twrangefix32.ItemType = itemType; - twrangefix32.MinValue = new TW_FIX32(min); - twrangefix32.MaxValue = new TW_FIX32(max); - twrangefix32.StepSize = new TW_FIX32(step); - twrangefix32.DefaultValue = new TW_FIX32(def); - twrangefix32.CurrentValue = new TW_FIX32(current); - Marshal.StructureToPtr(twrangefix32, lockedPtr, false); - } - break; - } - } - - static TWTY GetItemType() - { - var type = typeof(TValue); - if (type == typeof(TW_BOOL)) return TWTY.BOOL; - if (type == typeof(TW_FIX32)) return TWTY.FIX32; - if (type == typeof(TW_STR32)) return TWTY.STR32; - if (type == typeof(TW_STR64)) return TWTY.STR64; - if (type == typeof(TW_STR128)) return TWTY.STR128; - if (type == typeof(TW_STR255)) return TWTY.STR255; - if (type == typeof(TW_FRAME)) return TWTY.FRAME; - if (type == typeof(IntPtr)) return TWTY.HANDLE; - if (type == typeof(UIntPtr)) return TWTY.HANDLE; - - if (type.IsEnum) - { - type = type.GetEnumUnderlyingType(); - } - - if (type == typeof(ushort)) return TWTY.UINT16; - if (type == typeof(short)) return TWTY.INT16; - if (type == typeof(uint)) return TWTY.UINT32; - if (type == typeof(int)) return TWTY.INT32; - if (type == typeof(byte)) return TWTY.UINT8; - if (type == typeof(sbyte)) return TWTY.INT8; - - throw new NotSupportedException($"{type.Name} is not supported for writing."); - } - - /// - /// Writes single piece of value to the container pointer. - /// - /// - /// A locked pointer to the container's data pointer. If data is array this is the 0th item. - /// The twain type. - /// - /// Index of the item if pointer is array. - static void WriteContainerData(IntPtr intptr, TWTY type, TValue value, int itemIndex) where TValue : struct - { - switch (type) - { - default: - throw new NotSupportedException($"Unsupported item type {type} for writing."); - // TODO: for small types needs to fill whole int32 before writing? - case TWTY.HANDLE: - intptr += IntPtr.Size * itemIndex; - Marshal.StructureToPtr(value, intptr, false); - break; - case TWTY.INT8: - intptr += 1 * itemIndex; - //int intval = Convert.ToSByte(value); - //Marshal.StructureToPtr(intval, intptr, false); - Marshal.StructureToPtr(Convert.ToSByte(value), intptr, false); - break; - case TWTY.UINT8: - intptr += 1 * itemIndex; - //uint uintval = Convert.ToByte(value); - //Marshal.StructureToPtr(uintval, intptr, false); - Marshal.StructureToPtr(Convert.ToByte(value), intptr, false); - break; - case TWTY.INT16: - intptr += 2 * itemIndex; - //intval = Convert.ToInt16(value); - //Marshal.StructureToPtr(intval, intptr, false); - Marshal.StructureToPtr(Convert.ToInt16(value), intptr, false); - break; - case TWTY.BOOL: - case TWTY.UINT16: - intptr += 2 * itemIndex; - //uintval = Convert.ToUInt16(value); - //Marshal.StructureToPtr(uintval, intptr, false); - Marshal.StructureToPtr(Convert.ToUInt16(value), intptr, false); - break; - case TWTY.INT32: - intptr += 4 * itemIndex; - Marshal.StructureToPtr(Convert.ToInt32(value), intptr, false); - break; - case TWTY.UINT32: - intptr += 4 * itemIndex; - Marshal.StructureToPtr(Convert.ToUInt32(value), intptr, false); - break; - case TWTY.FIX32: - intptr += 4 * itemIndex; - Marshal.StructureToPtr(value, intptr, false); - break; - case TWTY.FRAME: - intptr += 16 * itemIndex; - Marshal.StructureToPtr(value, intptr, false); - break; - case TWTY.STR32: - intptr += TW_STR32.Size * itemIndex; - Marshal.StructureToPtr(value, intptr, false); - break; - case TWTY.STR64: - intptr += TW_STR64.Size * itemIndex; - Marshal.StructureToPtr(value, intptr, false); - break; - case TWTY.STR128: - intptr += TW_STR128.Size * itemIndex; - Marshal.StructureToPtr(value, intptr, false); - break; - case TWTY.STR255: - intptr += TW_STR255.Size * itemIndex; - Marshal.StructureToPtr(value, intptr, false); - break; - } + default: + throw new NotSupportedException($"Unsupported item type {type} for writing."); + // TODO: for small types needs to fill whole int32 before writing? + case TWTY.HANDLE: + intptr += IntPtr.Size * itemIndex; + Marshal.StructureToPtr(value, intptr, false); + break; + case TWTY.INT8: + intptr += 1 * itemIndex; + //int intval = Convert.ToSByte(value); + //Marshal.StructureToPtr(intval, intptr, false); + Marshal.StructureToPtr(Convert.ToSByte(value), intptr, false); + break; + case TWTY.UINT8: + intptr += 1 * itemIndex; + //uint uintval = Convert.ToByte(value); + //Marshal.StructureToPtr(uintval, intptr, false); + Marshal.StructureToPtr(Convert.ToByte(value), intptr, false); + break; + case TWTY.INT16: + intptr += 2 * itemIndex; + //intval = Convert.ToInt16(value); + //Marshal.StructureToPtr(intval, intptr, false); + Marshal.StructureToPtr(Convert.ToInt16(value), intptr, false); + break; + case TWTY.BOOL: + case TWTY.UINT16: + intptr += 2 * itemIndex; + //uintval = Convert.ToUInt16(value); + //Marshal.StructureToPtr(uintval, intptr, false); + Marshal.StructureToPtr(Convert.ToUInt16(value), intptr, false); + break; + case TWTY.INT32: + intptr += 4 * itemIndex; + Marshal.StructureToPtr(Convert.ToInt32(value), intptr, false); + break; + case TWTY.UINT32: + intptr += 4 * itemIndex; + Marshal.StructureToPtr(Convert.ToUInt32(value), intptr, false); + break; + case TWTY.FIX32: + intptr += 4 * itemIndex; + Marshal.StructureToPtr(value, intptr, false); + break; + case TWTY.FRAME: + intptr += 16 * itemIndex; + Marshal.StructureToPtr(value, intptr, false); + break; + case TWTY.STR32: + intptr += TW_STR32.Size * itemIndex; + Marshal.StructureToPtr(value, intptr, false); + break; + case TWTY.STR64: + intptr += TW_STR64.Size * itemIndex; + Marshal.StructureToPtr(value, intptr, false); + break; + case TWTY.STR128: + intptr += TW_STR128.Size * itemIndex; + Marshal.StructureToPtr(value, intptr, false); + break; + case TWTY.STR255: + intptr += TW_STR255.Size * itemIndex; + Marshal.StructureToPtr(value, intptr, false); + break; } } } diff --git a/src/NTwain/Events/EventHandler.cs b/src/NTwain/Events/EventHandler.cs new file mode 100644 index 0000000..bcc3d3d --- /dev/null +++ b/src/NTwain/Events/EventHandler.cs @@ -0,0 +1,12 @@ +#if !NET10_0_OR_GREATER +namespace NTwain.Events; + +/// +/// An event handler delegate with typed sender and arguments. +/// +/// +/// +/// +/// +public delegate void EventHandler(TSender sender, TArgs args); +#endif \ No newline at end of file diff --git a/src/NTwain/Events/TransferErrorEventArgs.cs b/src/NTwain/Events/TransferErrorEventArgs.cs new file mode 100644 index 0000000..6240f0b --- /dev/null +++ b/src/NTwain/Events/TransferErrorEventArgs.cs @@ -0,0 +1,48 @@ +using NTwain.Data; +using System; + +namespace NTwain.Events; + +/// +/// Contains TWAIN codes and source status when an error is encountered during transfer. +/// +public class TransferErrorEventArgs : EventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The error. + /// + public TransferErrorEventArgs(Exception error, string phase) + { + Exception = error; + Phase = phase; + } + + /// + /// Initializes a new instance of the class. + /// + /// The code. + /// + public TransferErrorEventArgs(STS code, string phase) + { + Code = code; + Phase = phase; + } + + /// + /// Gets the transfer phase the error occurred in. + /// + public string Phase { get; private set; } + + /// + /// Gets the return code or condition code if error is from DSM calls. + /// + public STS? Code { get; private set; } + + /// + /// Gets the exception if the error is from some exception + /// and not from TWAIN. + /// + public Exception? Exception { get; private set; } +} diff --git a/src/NTwain/Events/TransferReadyEventArgs.cs b/src/NTwain/Events/TransferReadyEventArgs.cs new file mode 100644 index 0000000..7e66485 --- /dev/null +++ b/src/NTwain/Events/TransferReadyEventArgs.cs @@ -0,0 +1,139 @@ +using NTwain.Data; +using NTwain.Triplets; +using System; + +namespace NTwain.Events; + +/// +/// Contains event data when a data transfer is ready to be processed. +/// +public class TransferReadyEventArgs : EventArgs +{ + public TransferReadyEventArgs(TwainAppSession twain, TWSX imageXferMech, TWSX audioXferMech) + { + _twain = twain; + XferType = XferType.Image; + ImgXferMech = imageXferMech; + AudXferMech = audioXferMech; + } + + /// + /// Update pending info and reset cancel flag. + /// + /// + public void UpdatePending(ref TW_PENDINGXFERS pending) + { + Cancel = CancelType.None; + PendingCount = pending.Count; + EndOfJobFlag = (TWEJ)pending.EOJ; + } + + /// + /// Gets or sets whether to cancel the transfer. + /// + public CancelType Cancel { get; set; } + + /// + /// Gets the end of job flag value for this transfer if job control is enabled. + /// + public TWEJ EndOfJobFlag { get; private set; } + + /// + /// Choose the type of transfer to use with the current device. + /// + public XferType XferType { get; set; } + + /// + /// Gets the current transfer mech if working with images. + /// + public TWSX ImgXferMech { get; } + + /// + /// Gets the current transfer mech if working with audio. + /// + public TWSX AudXferMech { get; } + + /// + /// Gets the known pending transfer count. This may not be appilicable + /// for certain scanning modes. + /// + public int PendingCount { get; private set; } + + private readonly TwainAppSession _twain; + + /// + /// If the transfer mech is file-related, + /// setup the file transfer options here. + /// + /// + /// + public STS SetupFileTransfer(ref TW_SETUPFILEXFER fileXfer) + { + if (_twain.CurrentSource == null) return default; + + return _twain.WrapInSTS(DGControl.SetupFileXfer.Set(_twain.AppIdentity, _twain.CurrentSource, ref fileXfer)); + } + + /// + /// Gets the ext image info at this state for Kodak devices. Use any utility methods on it + /// to read the data. Remember to call + /// when done. + /// + /// Container to query. Can be created with + /// + public STS GetExtendedImageInfo(ref TW_EXTIMAGEINFO container) + { + if (_twain.CurrentSource == null) return default; + + return _twain.WrapInSTS(DGImage.ExtImageInfo.GetSpecial(_twain.AppIdentity, _twain.CurrentSource, ref container)); + } + + //TW_IMAGEINFO? _imgInfo; + ///// + ///// Gets the tentative image information for the current transfer if applicable. + ///// This may differ from the final image depending on the transfer mode used (mostly when doing mem xfer). + ///// + //public TW_IMAGEINFO? PendingImageInfo + //{ + // get + // { + // // only get it if requested since it could be slow + // if (!_imgInfo.HasValue) + // { + // if (_twain.GetImageInfo(out TW_IMAGEINFO info).RC == TWRC.SUCCESS) + // { + // _imgInfo = info; + // } + // } + // return _imgInfo; + // } + //} + +} + +public enum CancelType +{ + /// + /// No cancel. + /// + None, + /// + /// Skips current transfer. + /// + SkipCurrent, + /// + /// Stops feeder but continue receiving already scanned images in the app. + /// + Graceful, + /// + /// Stops feeder and discard any pending images. + /// + EndNow +} + +public enum XferType +{ + Image, + Audio +} + diff --git a/src/NTwain/TransferredEventArgs.cs b/src/NTwain/Events/TransferredEventArgs.cs similarity index 76% rename from src/NTwain/TransferredEventArgs.cs rename to src/NTwain/Events/TransferredEventArgs.cs index 264418f..fe9f607 100644 --- a/src/NTwain/TransferredEventArgs.cs +++ b/src/NTwain/Events/TransferredEventArgs.cs @@ -1,29 +1,30 @@ using NTwain.Data; +using NTwain.Triplets; using System; -namespace NTwain -{ +namespace NTwain.Events; - public class TransferredEventArgs : EventArgs, IDisposable - { + +public class TransferredEventArgs : EventArgs, IDisposable +{ public TransferredEventArgs(TW_AUDIOINFO info, TW_SETUPFILEXFER fileInfo) { - AudioInfo = info; - FileInfo = fileInfo; + AudioInfo = info; + FileInfo = fileInfo; } public TransferredEventArgs(TW_AUDIOINFO info, BufferedData data) { - AudioInfo = info; - _data = data; + AudioInfo = info; + _data = data; } public TransferredEventArgs(TwainAppSession twain, TW_IMAGEINFO info, TW_SETUPFILEXFER? fileInfo, BufferedData? data) { - ImageInfo = info; - FileInfo = fileInfo; - IsImage = true; - _data = data; - _twain = twain; + ImageInfo = info; + FileInfo = fileInfo; + IsImage = true; + _data = data; + _twain = twain; } TwainAppSession? _twain; @@ -67,13 +68,13 @@ namespace NTwain /// public STS GetExtendedImageInfo(ref TW_EXTIMAGEINFO container) { - if (_twain == null) return default; - return _twain.GetExtendedImageInfo(ref container); + if (_twain == null || _twain.CurrentSource == null) return default; + + return _twain.WrapInSTS(DGImage.ExtImageInfo.Get(_twain.AppIdentity, _twain.CurrentSource, ref container)); } public void Dispose() { - _data?.Dispose(); + _data?.Dispose(); } - } } \ No newline at end of file diff --git a/src/NTwain/IMemoryManager.cs b/src/NTwain/IMemoryManager.cs index 252a9dc..84510f8 100644 --- a/src/NTwain/IMemoryManager.cs +++ b/src/NTwain/IMemoryManager.cs @@ -1,16 +1,36 @@ using System; -namespace NTwain +namespace NTwain; + +/// +/// Something that can do the 4 memory mgmt +/// things required by TWAIN. +/// +public interface IMemoryManager { - /// - /// Something that can do the 4 memory mgmt - /// things required by TWAIN. - /// - public interface IMemoryManager - { + /// + /// Allocates a block of memory of the specified size. + /// + /// The size in bytes to allocate. + /// A handle to the allocated memory block. IntPtr Alloc(uint size); + + /// + /// Frees a previously allocated memory block. + /// + /// The handle returned from . void Free(IntPtr handle); + + /// + /// Locks a memory block and returns a pointer to access its contents. + /// + /// The handle returned from . + /// A pointer to the locked memory block. IntPtr Lock(IntPtr handle); + + /// + /// Unlocks a previously locked memory block. + /// + /// The handle returned from . void Unlock(IntPtr handle); - } } \ No newline at end of file diff --git a/src/NTwain/Imaging/BITMAP.cs b/src/NTwain/Imaging/BITMAP.cs new file mode 100644 index 0000000..f8ab56e --- /dev/null +++ b/src/NTwain/Imaging/BITMAP.cs @@ -0,0 +1,253 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace Windows.Win32.Graphics.Gdi; + +// this is a good read +// http://atlc.sourceforge.net/bmp.html + + +partial struct BITMAPINFOHEADER +{ + const double METER_INCH_RATIO = 39.3700787; + + /// + /// Gets the horizontal dpi of the bitmap. + /// + /// + public float GetXDpi() + { + return (float)Math.Round(biXPelsPerMeter / METER_INCH_RATIO, 0); + } + /// + /// Gets the vertical dpi of the bitmap. + /// + /// + public float GetYDpi() + { + return (float)Math.Round(biYPelsPerMeter / METER_INCH_RATIO, 0); + } + /// + /// Gets the size of the structure. + /// + /// + public static uint GetByteSize() + { + return (uint)Marshal.SizeOf(); + } + /// + /// Checks to see if this structure contain valid data. + /// It also fills in any missing pieces if possible. + /// + /// + public bool Validate() + { + if (biHeight != 0 && biWidth != 0 && biBitCount != 0) + { + if (biSize == 0) + { + biSize = GetByteSize(); + } + if (biClrUsed == 0) + { + switch (biBitCount) + { + case 1: + biClrUsed = 2; + break; + case 4: + biClrUsed = 16; + break; + case 8: + biClrUsed = 256; + break; + } + } + if (biSizeImage == 0) + { + biSizeImage = (uint)(((( + biWidth * biBitCount) + 31) & ~31) >> 3) * (uint)Math.Abs(biHeight); + } + + return true; + } + return false; + } + + /// + /// Gets the pointer to scan0 given the header pointer. + /// + /// The header PTR. + /// + public IntPtr GetScan0(IntPtr headerPtr) + { + int p = (int)biClrUsed; + if ((p == 0) && (biBitCount <= 8)) + { + p = 1 << biBitCount; + } + p = (p * 4) + (int)biSize + headerPtr.ToInt32(); + return new IntPtr(p); + } + + /// + /// Gets whether the bitmap is bottom-up or top-down format. + /// + /// + /// true if this instance is bottom up image; otherwise, false. + /// + /// + public bool IsBottomUpImage + { + get + { + return biHeight > 0; + } + } + + + ///// + ///// Gets the System.Drawing pixel format of current structure. + ///// + ///// + //public PixelFormat GetDrawingPixelFormat() + //{ + // switch (biBitCount) + // { + // case 1: + // return PixelFormat.Format1bppIndexed; + // case 4: + // return PixelFormat.Format4bppIndexed; + // case 8: + // return PixelFormat.Format8bppIndexed; + // case 16: + // return PixelFormat.Format16bppRgb565; + // case 24: + // return PixelFormat.Format24bppRgb; + // case 32: + // return PixelFormat.Format32bppRgb; + // case 48: + // return PixelFormat.Format48bppRgb; + // } + // return PixelFormat.DontCare; + //} + + ///// + ///// Gets the color palette that's contained in the header. + ///// Note not all images will have palette, so check if the return value + ///// is null before using it. + ///// + ///// + //public ColorPalette? GetDrawingPalette(IntPtr headerPtr) + //{ + // //if (format == PixelFormat.Format8bppIndexed) + // //{ + // // // update color palette to grayscale version + // // ColorPalette grayPallet = bitmap.Palette; + // // for (int i = 0; i < grayPallet.Entries.Length; i++) + // // { + // // grayPallet.Entries[i] = Color.FromArgb(i, i, i); + // // } + // // bitmap.Palette = grayPallet; // this is what makes the gray pallet take effect + // //} + + // if (biClrUsed > 0) + // { + // byte[] data = new byte[biClrUsed * 4]; + // Marshal.Copy(new IntPtr(headerPtr.ToInt32() + biSize), data, 0, data.Length); + // var dummy = new System.Drawing.Bitmap(1, 1, GetDrawingPixelFormat()); + // ColorPalette pal = dummy.Palette; + // dummy.Dispose(); + // int index = 0; + // int setCount = data.Length / 4; + // for (int i = 0; i < setCount; i++) + // { + // index = i * 4; + // pal.Entries[i] = Color.FromArgb(data[index + 2], data[index + 1], data[index]); + // } + // return pal; + // } + // return null; + //} + + /// + /// Gets the stride size of this bitmap. + /// + /// + public int GetStride() + { + int bitsPerRow = (biBitCount * biWidth); + int strideTest = bitsPerRow / 8 + (bitsPerRow % 8 != 0 ? 1 : 0); + int overage = strideTest % 4; + if (overage > 0) + { + strideTest += (4 - overage); + } + return strideTest; + } + + /// + public override string ToString() + { + return new StringBuilder().Append("BitmapInfoHeader:") + .Append("\r\n\tSize = " + biSize) + .Append("\r\n\tWidth = " + biWidth) + .Append("\r\n\tHeight = " + biHeight) + .Append("\r\n\tPlanes = " + biPlanes) + .Append("\r\n\tBitCount = " + biBitCount) + .Append("\r\n\tCompression = " + Compression) + .Append("\r\n\tSizeImage = " + biSizeImage) + .Append("\r\n\tXPixelsPerMeter = " + biXPelsPerMeter) + .Append("\r\n\tYPixelsPerMeter = " + biYPelsPerMeter) + .Append("\r\n\tColorUsed = " + biClrUsed) + .Append("\r\n\tColorImportant = " + biClrImportant).ToString(); + } + + /// + /// Gets the bitmap compression type. + /// + public CompressionType Compression { get { return (CompressionType)biCompression; } } + + /// + /// Indicates the bitmap compression of . + /// + public enum CompressionType : uint + { + /// + /// An uncompressed format. + /// + BI_RGB = 0, + /// + /// A run-length encoded (RLE) format for bitmaps with 8 bpp. The compression format is a 2-byte format consisting of a count byte followed by a byte containing a color index. For more information, see Bitmap Compression. + /// + BI_RLE8 = 1, + /// + /// An RLE, format for bitmaps with 4 bpp. The compression format is a 2-byte format consisting of a count byte followed by two word-length color indexes. For more information, see Bitmap Compression. + /// + BI_RLE4 = 2, + /// + /// Specifies that the bitmap is not compressed and that the color table consists of three DWORD color masks that specify the red, green, and blue components of each pixel. + /// This is valid when used with 16- and 32-bpp bitmaps. + /// + BI_BITFIELDS = 3, + /// + /// Indicates that the image is a JPEG image. + /// + BI_JPEG = 4, + /// + /// Indicates that the image is a PNG image. + /// + BI_PNG = 5 + } +} + +//[StructLayout(LayoutKind.Sequential, Pack = 1)] +//struct BITMAPFILEHEADER +//{ +// public ushort bfType; +// public uint bfSize; +// public ushort bfReserved1; +// public ushort bfReserved2; +// public uint bfOffBits; +//} diff --git a/src/NTwain/Imaging/ImageTools.cs b/src/NTwain/Imaging/ImageTools.cs new file mode 100644 index 0000000..4dd0903 --- /dev/null +++ b/src/NTwain/Imaging/ImageTools.cs @@ -0,0 +1,145 @@ +using NTwain.Data; +using System; +using System.Runtime.InteropServices; +using Windows.Win32.Graphics.Gdi; + +namespace NTwain.Imaging; + +static class ImageTools +{ + // this is modified from twain cs sample + // http://sourceforge.net/projects/twainforcsharp/?source=typ_redirect + + public static bool IsDib(IntPtr data) + { + // a quick check not guaranteed correct, + // compare first 2 bytes to size of struct (which is also the first field) + var test = Marshal.ReadInt16(data); + // should be 40 + return test == BITMAPINFOHEADER.GetByteSize(); + } + public static bool IsTiff(IntPtr data) + { + var test = Marshal.ReadInt16(data); + // should be II + return test == 0x4949; + } + + public static unsafe BufferedData? GetBitmapData(IntPtr data) + { + var infoHeader = Marshal.PtrToStructure(data); + if (infoHeader.Validate()) + { + var fileHeaderSize = Marshal.SizeOf(); + + var fileHeader = new BITMAPFILEHEADER + { + bfType = 0x4D42, // "BM" + bfOffBits = (uint)fileHeaderSize + + infoHeader.biSize + + (infoHeader.biClrUsed * 4) + }; + fileHeader.bfSize = fileHeader.bfOffBits + infoHeader.biSizeImage; + + var dataCopy = BufferedData.MemPool.Rent((int)fileHeader.bfSize); // new byte[fileHeader.bfSize]; + + // TODO: run benchmark on which one is faster + + // write file header + //IntPtr tempPtr = Marshal.AllocHGlobal(fileHeaderSize); + //Marshal.StructureToPtr(fileHeader, tempPtr, true); + //Marshal.Copy(tempPtr, dataCopy, 0, fileHeaderSize); + //Marshal.FreeHGlobal(tempPtr); + + // would this be faster? + fixed (byte* p = dataCopy) + { + Marshal.StructureToPtr(fileHeader, (IntPtr)p, false); + } + + // write image + Marshal.Copy(data, dataCopy, fileHeaderSize, (int)fileHeader.bfSize - fileHeaderSize); + return new BufferedData(dataCopy, (int)fileHeader.bfSize, true); + } + return default; + } + + public static BufferedData? GetTiffData(IntPtr data) + { + // Find the size of the image so we can turn it into a memory stream... + var headerSize = Marshal.SizeOf(); + var tagSize = Marshal.SizeOf(); + var tiffSize = 0; + var tagPtr = data.ToInt64() + headerSize; + for (int i = 0; i < 999; i++) + { + tagPtr += (tagSize * i); + var tag = Marshal.PtrToStructure((IntPtr)tagPtr); + + switch (tag.u16Tag) + { + case 273: // StripOffsets... + case 279: // StripByteCounts... + tiffSize += (int)tag.u32Value; + break; + } + } + + if (tiffSize > 0) + { + var dataCopy = BufferedData.MemPool.Rent(tiffSize);// new byte[tiffSize]; + Marshal.Copy(data, dataCopy, 0, tiffSize); + return new BufferedData(dataCopy, tiffSize, true); + } + return default; + } + + //internal static Bitmap ReadBitmapImage(IntPtr data) + //{ + // Bitmap finalImg = null; + // Bitmap tempImg = null; + // try + // { + // var header = (BITMAPINFOHEADER)Marshal.PtrToStructure(data, typeof(BITMAPINFOHEADER)); + + // if (header.Validate()) + // { + // PixelFormat format = header.GetDrawingPixelFormat(); + // tempImg = new Bitmap(header.biWidth, Math.Abs(header.biHeight), header.GetStride(), format, header.GetScan0(data)); + // ColorPalette pal = header.GetDrawingPalette(data); + // if (pal != null) + // { + // tempImg.Palette = pal; + // } + // float xdpi = header.GetXDpi(); + // float ydpi = header.GetYDpi(); + // if (xdpi != 0 && ydpi == 0) + // { + // ydpi = xdpi; + // } + // else if (ydpi != 0 && xdpi == 0) + // { + // xdpi = ydpi; + // } + // if (xdpi != 0) + // { + // tempImg.SetResolution(xdpi, ydpi); + // } + // if (header.IsBottomUpImage) + // { + // tempImg.RotateFlip(RotateFlipType.RotateNoneFlipY); + // } + // finalImg = tempImg; + // tempImg = null; + // } + // } + // finally + // { + // if (tempImg != null) + // { + // tempImg.Dispose(); + // } + // } + // return finalImg; + //} +} diff --git a/src/NTwain/Native/TIFF.cs b/src/NTwain/Imaging/TIFF.cs similarity index 87% rename from src/NTwain/Native/TIFF.cs rename to src/NTwain/Imaging/TIFF.cs index 5e34a42..ef742a0 100644 --- a/src/NTwain/Native/TIFF.cs +++ b/src/NTwain/Imaging/TIFF.cs @@ -44,32 +44,30 @@ using System.Runtime.InteropServices; -namespace NTwain.Native +namespace NTwain.Imaging; + +/// +/// The TIFF file header. +/// Needed for supporting DAT.IMAGENATIVEXFER... +/// +[StructLayout(LayoutKind.Sequential, Pack = 1)] +struct TIFFHEADER { - /// - /// The TIFF file header. - /// Needed for supporting DAT.IMAGENATIVEXFER... - /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct TIFFHEADER - { public ushort u8ByteOrder; public ushort u16Version; public uint u32OffsetFirstIFD; public ushort u16u16IFD; - } +} - /// - /// An individual TIFF Tag. - /// Needed for supporting DAT.IMAGENATIVEXFER... - /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - struct TIFFTAG - { +/// +/// An individual TIFF Tag. +/// Needed for supporting DAT.IMAGENATIVEXFER... +/// +[StructLayout(LayoutKind.Sequential, Pack = 1)] +struct TIFFTAG +{ public ushort u16Tag; public ushort u16Type; public uint u32Count; public uint u32Value; - } - } diff --git a/src/NTwain/MessagePumpThread.cs b/src/NTwain/MessagePumpThread.cs deleted file mode 100644 index 73a906f..0000000 --- a/src/NTwain/MessagePumpThread.cs +++ /dev/null @@ -1,173 +0,0 @@ -#if WINDOWS || NETFRAMEWORK -using Microsoft.Extensions.Logging; -using NTwain.Data; -using System; -using System.Runtime.InteropServices; -using System.Threading; -using System.Threading.Tasks; -using System.Windows.Forms; - -namespace NTwain -{ - /// - /// For use under Windows to host a message pump. - /// - class MessagePumpThread - { - KeepAliveForm? _dummyForm; - TwainAppSession? _twain; - - public bool IsRunning => _dummyForm != null && _dummyForm.IsHandleCreated; - - /// - /// Starts the thread, attaches a twain session to it, - /// and opens the DSM. - /// - /// - /// - /// - public async Task AttachAsync(TwainAppSession twain) - { - if (twain.State > STATE.S2) throw new InvalidOperationException("Cannot attach to an opened TWAIN session."); - if (_twain != null || _dummyForm != null) throw new InvalidOperationException("Already attached previously."); - - Thread t = new(RunMessagePump); - t.IsBackground = true; - t.SetApartmentState(ApartmentState.STA); - t.Start(); - - while (_dummyForm == null || !_dummyForm.IsHandleCreated) - { - await Task.Delay(50); - } - - STS sts = default; - TaskCompletionSource tcs = new(); - _dummyForm.BeginInvoke(() => - { - try - { - sts = twain.OpenDSM(_dummyForm.Handle, SynchronizationContext.Current!); - if (sts.IsSuccess) - { - twain.AddWinformFilter(); - _twain = twain; - } - else - { - _dummyForm.Close(true); - } - } - finally - { - tcs.TrySetResult(true); - } - }); - await tcs.Task; - return sts; - } - - /// - /// Detatches a previously attached session and stops the thread. - /// - public async Task DetachAsync() - { - STS sts = default; - if (_dummyForm != null && _twain != null) - { - TaskCompletionSource tcs = new(); - _dummyForm.BeginInvoke(() => - { - sts = _twain.CloseDSMReal(); - if (sts.IsSuccess) - { - _twain.RemoveWinformFilter(); - _dummyForm.Close(true); - _twain = null; - } - tcs.SetResult(sts); - }); - await tcs.Task; - } - return sts; - } - - public void BringWindowToFront() - { - if (_dummyForm != null) - { - _dummyForm.BeginInvoke(_dummyForm.BringToFront); - } - } - - void RunMessagePump() - { - _twain?.Logger.LogDebug("Starting TWAIN message pump thread."); - Application.ThreadException += Application_ThreadException; - Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); - _dummyForm = new KeepAliveForm(); - _dummyForm.FormClosed += (s, e) => - { - _dummyForm = null; - }; - Application.Run(_dummyForm); - _twain?.Logger.LogDebug("TWAIN message pump thread exiting."); - } - - private void Application_ThreadException(object sender, ThreadExceptionEventArgs e) - { - _twain?.Logger.LogError(e.Exception, "Unhandled exception in TWAIN message pump thread."); - } - - class KeepAliveForm : Form - { - public KeepAliveForm() - { - ShowInTaskbar = false; - } - - [DllImport("user32.dll")] - static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent); - - protected override void OnHandleCreated(EventArgs e) - { - base.OnHandleCreated(e); - SetParent(this.Handle, new IntPtr(-3)); // HWND_MESSAGE - } - - //protected override CreateParams CreateParams - //{ - // get - // { - // CreateParams cp = base.CreateParams; - // cp.ExStyle |= 0x80; // WS_EX_TOOLWINDOW - // return cp; - // } - //} - - //protected override void OnShown(EventArgs e) - //{ - // Hide(); - // base.OnShown(e); - //} - - bool _closeForReal = false; - internal void Close(bool forReal) - { - _closeForReal = forReal; - Close(); - } - - protected override void OnFormClosing(FormClosingEventArgs e) - { - if (e.CloseReason == CloseReason.UserClosing && !_closeForReal) - { - e.Cancel = true; - Hide(); - } - base.OnFormClosing(e); - } - } - } -} -#endif \ No newline at end of file diff --git a/src/NTwain/NTwain.csproj b/src/NTwain/NTwain.csproj index 16e5d8f..fa68c0d 100644 --- a/src/NTwain/NTwain.csproj +++ b/src/NTwain/NTwain.csproj @@ -3,21 +3,23 @@ NTwain Library containing the TWAIN API for dotnet. - net8.0;net8.0-windows;net9.0;net9.0-windows;net10.0;net10.0-windows;net472; + + net8.0;net9.0;net10.0;net462; enable true + true - + - + - + @@ -35,7 +37,6 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - True @@ -47,8 +48,7 @@ DSMGenerator.dummy - - + diff --git a/src/NTwain/Native/BITMAP.cs b/src/NTwain/Native/BITMAP.cs deleted file mode 100644 index d83e016..0000000 --- a/src/NTwain/Native/BITMAP.cs +++ /dev/null @@ -1,254 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using System.Text; - -namespace Windows.Win32.Graphics.Gdi -{ - // this is a good read - // http://atlc.sourceforge.net/bmp.html - - - partial struct BITMAPINFOHEADER - { - const double METER_INCH_RATIO = 39.3700787; - - /// - /// Gets the horizontal dpi of the bitmap. - /// - /// - public float GetXDpi() - { - return (float)Math.Round(biXPelsPerMeter / METER_INCH_RATIO, 0); - } - /// - /// Gets the vertical dpi of the bitmap. - /// - /// - public float GetYDpi() - { - return (float)Math.Round(biYPelsPerMeter / METER_INCH_RATIO, 0); - } - /// - /// Gets the size of the structure. - /// - /// - public static uint GetByteSize() - { - return (uint)Marshal.SizeOf(); - } - /// - /// Checks to see if this structure contain valid data. - /// It also fills in any missing pieces if possible. - /// - /// - public bool Validate() - { - if (biHeight != 0 && biWidth != 0 && biBitCount != 0) - { - if (biSize == 0) - { - biSize = GetByteSize(); - } - if (biClrUsed == 0) - { - switch (biBitCount) - { - case 1: - biClrUsed = 2; - break; - case 4: - biClrUsed = 16; - break; - case 8: - biClrUsed = 256; - break; - } - } - if (biSizeImage == 0) - { - biSizeImage = (uint)(((( - biWidth * biBitCount) + 31) & ~31) >> 3) * (uint)Math.Abs(biHeight); - } - - return true; - } - return false; - } - - /// - /// Gets the pointer to scan0 given the header pointer. - /// - /// The header PTR. - /// - public IntPtr GetScan0(IntPtr headerPtr) - { - int p = (int)biClrUsed; - if ((p == 0) && (biBitCount <= 8)) - { - p = 1 << biBitCount; - } - p = (p * 4) + (int)biSize + headerPtr.ToInt32(); - return new IntPtr(p); - } - - /// - /// Gets whether the bitmap is bottom-up or top-down format. - /// - /// - /// true if this instance is bottom up image; otherwise, false. - /// - /// - public bool IsBottomUpImage - { - get - { - return biHeight > 0; - } - } - - - ///// - ///// Gets the System.Drawing pixel format of current structure. - ///// - ///// - //public PixelFormat GetDrawingPixelFormat() - //{ - // switch (biBitCount) - // { - // case 1: - // return PixelFormat.Format1bppIndexed; - // case 4: - // return PixelFormat.Format4bppIndexed; - // case 8: - // return PixelFormat.Format8bppIndexed; - // case 16: - // return PixelFormat.Format16bppRgb565; - // case 24: - // return PixelFormat.Format24bppRgb; - // case 32: - // return PixelFormat.Format32bppRgb; - // case 48: - // return PixelFormat.Format48bppRgb; - // } - // return PixelFormat.DontCare; - //} - - ///// - ///// Gets the color palette that's contained in the header. - ///// Note not all images will have palette, so check if the return value - ///// is null before using it. - ///// - ///// - //public ColorPalette? GetDrawingPalette(IntPtr headerPtr) - //{ - // //if (format == PixelFormat.Format8bppIndexed) - // //{ - // // // update color palette to grayscale version - // // ColorPalette grayPallet = bitmap.Palette; - // // for (int i = 0; i < grayPallet.Entries.Length; i++) - // // { - // // grayPallet.Entries[i] = Color.FromArgb(i, i, i); - // // } - // // bitmap.Palette = grayPallet; // this is what makes the gray pallet take effect - // //} - - // if (biClrUsed > 0) - // { - // byte[] data = new byte[biClrUsed * 4]; - // Marshal.Copy(new IntPtr(headerPtr.ToInt32() + biSize), data, 0, data.Length); - // var dummy = new System.Drawing.Bitmap(1, 1, GetDrawingPixelFormat()); - // ColorPalette pal = dummy.Palette; - // dummy.Dispose(); - // int index = 0; - // int setCount = data.Length / 4; - // for (int i = 0; i < setCount; i++) - // { - // index = i * 4; - // pal.Entries[i] = Color.FromArgb(data[index + 2], data[index + 1], data[index]); - // } - // return pal; - // } - // return null; - //} - - /// - /// Gets the stride size of this bitmap. - /// - /// - public int GetStride() - { - int bitsPerRow = (biBitCount * biWidth); - int strideTest = bitsPerRow / 8 + (bitsPerRow % 8 != 0 ? 1 : 0); - int overage = strideTest % 4; - if (overage > 0) - { - strideTest += (4 - overage); - } - return strideTest; - } - - /// - public override string ToString() - { - return new StringBuilder().Append("BitmapInfoHeader:") - .Append("\r\n\tSize = " + biSize) - .Append("\r\n\tWidth = " + biWidth) - .Append("\r\n\tHeight = " + biHeight) - .Append("\r\n\tPlanes = " + biPlanes) - .Append("\r\n\tBitCount = " + biBitCount) - .Append("\r\n\tCompression = " + Compression) - .Append("\r\n\tSizeImage = " + biSizeImage) - .Append("\r\n\tXPixelsPerMeter = " + biXPelsPerMeter) - .Append("\r\n\tYPixelsPerMeter = " + biYPelsPerMeter) - .Append("\r\n\tColorUsed = " + biClrUsed) - .Append("\r\n\tColorImportant = " + biClrImportant).ToString(); - } - - /// - /// Gets the bitmap compression type. - /// - public CompressionType Compression { get { return (CompressionType)biCompression; } } - - /// - /// Indicates the bitmap compression of . - /// - public enum CompressionType : uint - { - /// - /// An uncompressed format. - /// - BI_RGB = 0, - /// - /// A run-length encoded (RLE) format for bitmaps with 8 bpp. The compression format is a 2-byte format consisting of a count byte followed by a byte containing a color index. For more information, see Bitmap Compression. - /// - BI_RLE8 = 1, - /// - /// An RLE, format for bitmaps with 4 bpp. The compression format is a 2-byte format consisting of a count byte followed by two word-length color indexes. For more information, see Bitmap Compression. - /// - BI_RLE4 = 2, - /// - /// Specifies that the bitmap is not compressed and that the color table consists of three DWORD color masks that specify the red, green, and blue components of each pixel. - /// This is valid when used with 16- and 32-bpp bitmaps. - /// - BI_BITFIELDS = 3, - /// - /// Indicates that the image is a JPEG image. - /// - BI_JPEG = 4, - /// - /// Indicates that the image is a PNG image. - /// - BI_PNG = 5 - } - } - - //[StructLayout(LayoutKind.Sequential, Pack = 1)] - //struct BITMAPFILEHEADER - //{ - // public ushort bfType; - // public uint bfSize; - // public ushort bfReserved1; - // public ushort bfReserved2; - // public uint bfOffBits; - //} -} diff --git a/src/NTwain/Native/ImageTools.cs b/src/NTwain/Native/ImageTools.cs deleted file mode 100644 index 86ceec9..0000000 --- a/src/NTwain/Native/ImageTools.cs +++ /dev/null @@ -1,146 +0,0 @@ -using NTwain.Data; -using System; -using System.Runtime.InteropServices; -using Windows.Win32.Graphics.Gdi; - -namespace NTwain.Native -{ - static class ImageTools - { - // this is modified from twain cs sample - // http://sourceforge.net/projects/twainforcsharp/?source=typ_redirect - - public static bool IsDib(IntPtr data) - { - // a quick check not guaranteed correct, - // compare first 2 bytes to size of struct (which is also the first field) - var test = Marshal.ReadInt16(data); - // should be 40 - return test == BITMAPINFOHEADER.GetByteSize(); - } - public static bool IsTiff(IntPtr data) - { - var test = Marshal.ReadInt16(data); - // should be II - return test == 0x4949; - } - - public static unsafe BufferedData? GetBitmapData(IntPtr data) - { - var infoHeader = Marshal.PtrToStructure(data); - if (infoHeader.Validate()) - { - var fileHeaderSize = Marshal.SizeOf(); - - var fileHeader = new BITMAPFILEHEADER - { - bfType = 0x4D42, // "BM" - bfOffBits = (uint)fileHeaderSize + - infoHeader.biSize + - (infoHeader.biClrUsed * 4) - }; - fileHeader.bfSize = fileHeader.bfOffBits + infoHeader.biSizeImage; - - var dataCopy = BufferedData.MemPool.Rent((int)fileHeader.bfSize); // new byte[fileHeader.bfSize]; - - // TODO: run benchmark on which one is faster - - // write file header - //IntPtr tempPtr = Marshal.AllocHGlobal(fileHeaderSize); - //Marshal.StructureToPtr(fileHeader, tempPtr, true); - //Marshal.Copy(tempPtr, dataCopy, 0, fileHeaderSize); - //Marshal.FreeHGlobal(tempPtr); - - // would this be faster? - fixed (byte* p = dataCopy) - { - Marshal.StructureToPtr(fileHeader, (IntPtr)p, false); - } - - // write image - Marshal.Copy(data, dataCopy, fileHeaderSize, (int)fileHeader.bfSize - fileHeaderSize); - return new BufferedData(dataCopy, (int)fileHeader.bfSize, true); - } - return default; - } - - public static BufferedData? GetTiffData(IntPtr data) - { - // Find the size of the image so we can turn it into a memory stream... - var headerSize = Marshal.SizeOf(); - var tagSize = Marshal.SizeOf(); - var tiffSize = 0; - var tagPtr = data.ToInt64() + headerSize; - for (int i = 0; i < 999; i++) - { - tagPtr += (tagSize * i); - var tag = Marshal.PtrToStructure((IntPtr)tagPtr); - - switch (tag.u16Tag) - { - case 273: // StripOffsets... - case 279: // StripByteCounts... - tiffSize += (int)tag.u32Value; - break; - } - } - - if (tiffSize > 0) - { - var dataCopy = BufferedData.MemPool.Rent(tiffSize);// new byte[tiffSize]; - Marshal.Copy(data, dataCopy, 0, tiffSize); - return new BufferedData(dataCopy, tiffSize, true); - } - return default; - } - - //internal static Bitmap ReadBitmapImage(IntPtr data) - //{ - // Bitmap finalImg = null; - // Bitmap tempImg = null; - // try - // { - // var header = (BITMAPINFOHEADER)Marshal.PtrToStructure(data, typeof(BITMAPINFOHEADER)); - - // if (header.Validate()) - // { - // PixelFormat format = header.GetDrawingPixelFormat(); - // tempImg = new Bitmap(header.biWidth, Math.Abs(header.biHeight), header.GetStride(), format, header.GetScan0(data)); - // ColorPalette pal = header.GetDrawingPalette(data); - // if (pal != null) - // { - // tempImg.Palette = pal; - // } - // float xdpi = header.GetXDpi(); - // float ydpi = header.GetYDpi(); - // if (xdpi != 0 && ydpi == 0) - // { - // ydpi = xdpi; - // } - // else if (ydpi != 0 && xdpi == 0) - // { - // xdpi = ydpi; - // } - // if (xdpi != 0) - // { - // tempImg.SetResolution(xdpi, ydpi); - // } - // if (header.IsBottomUpImage) - // { - // tempImg.RotateFlip(RotateFlipType.RotateNoneFlipY); - // } - // finalImg = tempImg; - // tempImg = null; - // } - // } - // finally - // { - // if (tempImg != null) - // { - // tempImg.Dispose(); - // } - // } - // return finalImg; - //} - } -} diff --git a/src/NTwain/Native/WIN_MESSAGE.cs b/src/NTwain/Native/WIN_MESSAGE.cs deleted file mode 100644 index b5a4899..0000000 --- a/src/NTwain/Native/WIN_MESSAGE.cs +++ /dev/null @@ -1,21 +0,0 @@ -//using System; -//using System.Runtime.InteropServices; - -//namespace NTwain.Native -//{ -// /// -// /// The MSG structure in Windows for TWAIN use. -// /// -// [StructLayout(LayoutKind.Sequential)] -// struct WIN_MESSAGE -// { -// public IntPtr hwnd; -// public uint message; -// public IntPtr wParam; -// public IntPtr lParam; -// uint _time; -// int _x; -// int _y; -// uint lprivate; -// } -//} diff --git a/src/NTwain/Native/WinNativeMethods.cs b/src/NTwain/Native/WinNativeMethods.cs deleted file mode 100644 index 18e80cc..0000000 --- a/src/NTwain/Native/WinNativeMethods.cs +++ /dev/null @@ -1,97 +0,0 @@ -//using System; -//using System.Runtime.InteropServices; - -//namespace NTwain.Native -//{ -// /// -// /// Native methods for windows. -// /// -// static partial class WinNativeMethods -// { -//#if NET7_0_OR_GREATER -// [LibraryImport("kernel32", SetLastError = true)] -// public static partial IntPtr GlobalAlloc(AllocFlag uFlags, UIntPtr dwBytes); - -// [LibraryImport("kernel32", SetLastError = true)] -// public static partial IntPtr GlobalFree(IntPtr hMem); - -// [LibraryImport("kernel32", SetLastError = true)] -// public static partial IntPtr GlobalLock(IntPtr handle); - -// [LibraryImport("kernel32", SetLastError = true)] -// [return: MarshalAs(UnmanagedType.Bool)] -// public static partial bool GlobalUnlock(IntPtr handle); -//#else -// [DllImport("kernel32", SetLastError = true)] -// public static extern IntPtr GlobalAlloc(AllocFlag uFlags, UIntPtr dwBytes); - -// [DllImport("kernel32", SetLastError = true)] -// public static extern IntPtr GlobalFree(IntPtr hMem); - -// [DllImport("kernel32", SetLastError = true)] -// public static extern IntPtr GlobalLock(IntPtr handle); - -// [DllImport("kernel32", SetLastError = true)] -// [return: MarshalAs(UnmanagedType.Bool)] -// public static extern bool GlobalUnlock(IntPtr handle); -//#endif - -// [Flags] -// public enum AllocFlag : uint -// { -// /// -// /// Allocates fixed memory. The return value is a pointer. -// /// -// GMEM_FIXED = 0, -// /// -// /// Allocates movable memory. Memory blocks are never moved in physical memory, but they can be moved within the default heap. -// /// The return value is a handle to the memory object. To translate the handle into a pointer, use the GlobalLock function. -// /// -// GMEM_MOVEABLE = 2, -// /// -// /// Initializes memory contents to zero. -// /// -// GMEM_ZEROINIT = 0x40, -// GPTR = GMEM_FIXED | GMEM_ZEROINIT, -// GHND = GMEM_MOVEABLE | GMEM_ZEROINIT -// } - -//// [Flags] -//// public enum PEEK_MESSAGE_REMOVE_TYPE : uint -//// { -//// PM_NOREMOVE = 0x00000000, -//// PM_REMOVE = 0x00000001, -//// PM_NOYIELD = 0x00000002, -//// PM_QS_INPUT = 0x04070000, -//// PM_QS_POSTMESSAGE = 0x00980000, -//// PM_QS_PAINT = 0x00200000, -//// PM_QS_SENDMESSAGE = 0x00400000, -//// } - -////#if NET7_0_OR_GREATER -//// [LibraryImport("USER32.dll")] -//// public static partial int PeekMessageW(ref WIN_MESSAGE lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax, PEEK_MESSAGE_REMOVE_TYPE wRemoveMsg); - -//// [LibraryImport("USER32.dll", SetLastError = true)] -//// public static partial int GetMessageW(ref WIN_MESSAGE lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax); - -//// [LibraryImport("USER32.dll")] -//// public static partial int TranslateMessage(ref WIN_MESSAGE lpMsg); - -//// [LibraryImport("USER32.dll")] -//// public static partial nint DispatchMessageW(ref WIN_MESSAGE lpMsg); -////#else -//// [DllImport("USER32.dll")] -//// public static extern int PeekMessageW(ref WIN_MESSAGE lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax, PEEK_MESSAGE_REMOVE_TYPE wRemoveMsg); - -//// [DllImport("USER32.dll", SetLastError = true)] -//// public static extern int GetMessageW(ref WIN_MESSAGE lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax); - -//// [DllImport("USER32.dll")] -//// public static extern int TranslateMessage(ref WIN_MESSAGE lpMsg); - -//// [DllImport("USER32.dll")] -//// public static extern nint DispatchMessageW(ref WIN_MESSAGE lpMsg); -////#endif -// } -//} diff --git a/src/NTwain/NativeMethods.json b/src/NTwain/NativeMethods.json deleted file mode 100644 index dacdfc7..0000000 --- a/src/NTwain/NativeMethods.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://aka.ms/CsWin32.schema.json", - "allowMarshaling": false -} \ No newline at end of file diff --git a/src/NTwain/NativeMethods.txt b/src/NTwain/NativeMethods.txt index 323cdf9..a09f65c 100644 --- a/src/NTwain/NativeMethods.txt +++ b/src/NTwain/NativeMethods.txt @@ -6,3 +6,28 @@ GlobalUnlock BITMAPINFOHEADER BITMAPINFO BITMAPFILEHEADER + +// Window class and creation +RegisterClassEx +UnregisterClass +CreateWindowEx +DestroyWindow +DefWindowProc +GetWindowLong +BringWindowToTop + +// Message loop +GetMessage +TranslateMessage +DispatchMessage +PostQuitMessage +PostMessage + +// System +GetModuleHandle +GetCurrentThreadId +LoadLibrary + +// Constants - Window Messages +WM_DESTROY +WM_APP diff --git a/src/NTwain/Platform/DllPath.cs b/src/NTwain/Platform/DllPath.cs new file mode 100644 index 0000000..09dcf49 --- /dev/null +++ b/src/NTwain/Platform/DllPath.cs @@ -0,0 +1,38 @@ +using NTwain.Data; +using System; +using System.IO; +using System.Reflection; +using System.Runtime.Versioning; +using Windows.Win32; + +namespace NTwain.Platform; + +static class DllPath +{ + static FreeLibrarySafeHandle _loadDllPtr = new(); + + /// + /// Try to add the runtimes/win-{arch}/native path to the DLL search path. + /// + /// +#if !NETFRAMEWORK + [SupportedOSPlatform("windows6.0.6000")] +#endif + public static void TryUseLocalDsm() + { + if (_loadDllPtr.IsInvalid == false) return; + + var arch = Environment.Is64BitProcess ? "x64" : "x86"; + var curFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + if (curFolder == null) return; + + var dsmFile = Path.Combine(curFolder, "twaindsm.dll"); + if (!File.Exists(dsmFile)) return; + + if (!TWPlatform.PreferLegacyDSM) + { + // try to preemptively load this dll into process before pinvoke does + _loadDllPtr = PInvoke.LoadLibrary(dsmFile); + } + } +} diff --git a/src/NTwain/Platform/FallbackMemoryManager.cs b/src/NTwain/Platform/FallbackMemoryManager.cs new file mode 100644 index 0000000..942e7e0 --- /dev/null +++ b/src/NTwain/Platform/FallbackMemoryManager.cs @@ -0,0 +1,35 @@ +using System; +using System.Runtime.InteropServices; + +namespace NTwain.Platform; + +/// +/// Manages memory allocation, locking, and freeing operations for TWAIN sessions. +/// +internal class FallbackMemoryManager : IMemoryManager +{ + /// + public IntPtr Alloc(uint size) + { + return Marshal.AllocHGlobal((int)size); + } + + /// + public void Free(IntPtr handle) + { + if (handle == IntPtr.Zero) return; + + Marshal.FreeHGlobal(handle); + } + + /// + public IntPtr Lock(IntPtr handle) + { + return handle; + } + + /// + public void Unlock(IntPtr handle) + { + } +} diff --git a/src/NTwain/Platform/TwainMemoryManager.cs b/src/NTwain/Platform/TwainMemoryManager.cs new file mode 100644 index 0000000..5be7eee --- /dev/null +++ b/src/NTwain/Platform/TwainMemoryManager.cs @@ -0,0 +1,51 @@ +using NTwain.Data; +using System; + +namespace NTwain.Platform; + +/// +/// Manages memory allocation, locking, and freeing operations for TWAIN sessions. +/// +internal class TwainMemoryManager : IMemoryManager +{ + private TW_ENTRYPOINT_DELEGATES _entryPoint; + + /// + /// Initializes a new instance of the class. + /// + /// The TWAIN entry point delegates for memory operations. + public TwainMemoryManager(TW_ENTRYPOINT_DELEGATES entryPoint) + { + _entryPoint = entryPoint; + } + + /// + public IntPtr Alloc(uint size) + { + return _entryPoint.DSM_MemAllocate(size); + } + + /// + public void Free(IntPtr handle) + { + if (handle == IntPtr.Zero) return; + + _entryPoint.DSM_MemFree(handle); + } + + /// + public IntPtr Lock(IntPtr handle) + { + if (handle == IntPtr.Zero) return IntPtr.Zero; + + return _entryPoint.DSM_MemLock(handle); + } + + /// + public void Unlock(IntPtr handle) + { + if (handle == IntPtr.Zero) return; + + _entryPoint.DSM_MemUnlock(handle); + } +} diff --git a/src/NTwain/Platform/Win32MemoryManager.cs b/src/NTwain/Platform/Win32MemoryManager.cs new file mode 100644 index 0000000..5a66a1d --- /dev/null +++ b/src/NTwain/Platform/Win32MemoryManager.cs @@ -0,0 +1,49 @@ +using System; +using System.Runtime.Versioning; +using Windows.Win32; +using Windows.Win32.Foundation; +using Windows.Win32.System.Memory; + +namespace NTwain.Platform; + +/// +/// Manages memory allocation, locking, and freeing operations for TWAIN sessions. +/// +#if !NETFRAMEWORK +[SupportedOSPlatform("windows5.1.2600")] +#endif +internal class Win32MemoryManager : IMemoryManager +{ + /// + public IntPtr Alloc(uint size) + { + return PInvoke.GlobalAlloc(GLOBAL_ALLOC_FLAGS.GHND, size); + } + + /// + public void Free(IntPtr handle) + { + if (handle == IntPtr.Zero) return; + + PInvoke.GlobalFree((HGLOBAL)handle); + } + + /// + public IntPtr Lock(IntPtr handle) + { + if (handle == IntPtr.Zero) return IntPtr.Zero; + + unsafe + { + return (IntPtr)PInvoke.GlobalLock((HGLOBAL)handle); + } + } + + /// + public void Unlock(IntPtr handle) + { + if (handle == IntPtr.Zero) return; + + PInvoke.GlobalUnlock((HGLOBAL)handle); + } +} diff --git a/src/NTwain/Platform/Win32MessagePump.cs b/src/NTwain/Platform/Win32MessagePump.cs new file mode 100644 index 0000000..c6508fb --- /dev/null +++ b/src/NTwain/Platform/Win32MessagePump.cs @@ -0,0 +1,521 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Runtime.Versioning; +using System.Threading; +using Windows.Win32; +using Windows.Win32.Foundation; +using Windows.Win32.Graphics.Gdi; +using Windows.Win32.UI.WindowsAndMessaging; + +namespace NTwain.Platform; + +// this piece was mostly generated by AI + + +// TODO: detect driver UI and call BringWindowToTop so it doesn't hide behind app window + +#if !NETFRAMEWORK +[SupportedOSPlatform("windows5.1.2600")] +#endif +internal sealed class Win32MessagePump : IDisposable +{ + private const string WindowClassName = "MsgPumpParkWindow"; + private const uint WM_APP_INVOKE = PInvoke.WM_APP + 1; + + private readonly FreeLibrarySafeHandle _hInstance; + private readonly uint _threadId; + private HWND _mainWindow; + private bool _disposed; + + // Store the delegate to prevent garbage collection + private static WNDPROC? s_wndProc; + + // Queue for work items posted to the UI thread + private readonly Queue _workQueue = new(); + private readonly object _workQueueLock = new(); + + // Message filters + private readonly List _messageFilters = new(); + private readonly object _messageFiltersLock = new(); + private readonly ILogger _logger; + + // SynchronizationContext + private Win32SynchronizationContext? _synchronizationContext; + + public Win32MessagePump(ILogger logger) + { + _hInstance = PInvoke.GetModuleHandle((string?)null); + _threadId = PInvoke.GetCurrentThreadId(); + _logger = logger; + } + + /// + /// Occurs when an unhandled exception is thrown during message processing. + /// + public event EventHandler? UnhandledException; + + /// + /// Gets the main (hidden) message window handle. + /// + public HWND MainWindow => _mainWindow; + + public bool InvokeRequired => PInvoke.GetCurrentThreadId() != _threadId; + + /// + /// Gets the SynchronizationContext associated with this message pump. + /// + public SynchronizationContext? SynchronizationContext => _synchronizationContext; + + /// + /// Adds a message filter to the application's message pump. + /// + public void AddMessageFilter(IWin32MessageFilter filter) + { + lock (_messageFiltersLock) + { + _messageFilters.Add(filter); + } + } + + /// + /// Removes a message filter from the application's message pump. + /// + public bool RemoveMessageFilter(IWin32MessageFilter filter) + { + lock (_messageFiltersLock) + { + return _messageFilters.Remove(filter); + } + } + + public int Run() + { + if (!RegisterWindowClass()) + { + _logger.LogError("Failed to register window class for message pump."); + return -1; + } + + if (!CreateMainWindow()) + { + _logger.LogError("Failed to create main window for message pump."); + UnregisterWindowClass(); + return -1; + } + + // Create and install the SynchronizationContext + _synchronizationContext = new Win32SynchronizationContext(this); + SynchronizationContext.SetSynchronizationContext(_synchronizationContext); + + int exitCode = RunMessageLoop(); + + // Clear the SynchronizationContext + SynchronizationContext.SetSynchronizationContext(null); + + Dispose(); + return exitCode; + } + + private bool RegisterWindowClass() + { + s_wndProc = WindowProc; + + unsafe + { + fixed (char* className = WindowClassName) + { + var wc = new WNDCLASSEXW + { + cbSize = (uint)Marshal.SizeOf(), + style = 0, + lpfnWndProc = s_wndProc, + cbClsExtra = 0, + cbWndExtra = 0, + hInstance = (HINSTANCE)_hInstance.DangerousGetHandle(), + hIcon = HICON.Null, + hCursor = HCURSOR.Null, + hbrBackground = HBRUSH.Null, + lpszMenuName = null, + lpszClassName = className, + hIconSm = HICON.Null + }; + + ushort atom = PInvoke.RegisterClassEx(in wc); + if (atom == 0) + { + return false; + } + } + } + + return true; + } + + private void UnregisterWindowClass() + { + PInvoke.UnregisterClass(WindowClassName, _hInstance); + } + + private bool CreateMainWindow() + { + unsafe + { + _mainWindow = PInvoke.CreateWindowEx( + 0, + WindowClassName, + "MsgPump Window", + 0, + 0, 0, 0, 0, + new HWND(unchecked((nint)(-3))), // HWND_MESSAGE + null, + _hInstance, + null); + } + + Debug.WriteLine($"Pump Window Handle={_mainWindow}"); + + return !_mainWindow.IsNull; + } + + private int RunMessageLoop() + { + _logger.LogInformation("Starting Win32 message loop."); + MSG msg; + + while (true) + { + int result; + unsafe + { + result = PInvoke.GetMessage(&msg, HWND.Null, 0, 0); + } + + if (result == 0) // WM_QUIT + { + return (int)msg.wParam.Value; + } + + if (result == -1) // Error + { + return -1; + } + + ProcessWorkQueue(); + + if (FilterMessage(ref msg)) + { + continue; + } + + PInvoke.TranslateMessage(in msg); + PInvoke.DispatchMessage(in msg); + + //if (msg.hwnd.IsNull == false) + //{ + // var style = PInvoke.GetWindowLong(msg.hwnd, WINDOW_LONG_PTR_INDEX.GWL_STYLE); + // var isTop = (style & WS_CHILD) != WS_CHILD; + // if (isTop) + // { + // //SeenHwnds[msg.hwnd] = isTop; + // Debug.WriteLine($"Dispatched message 0x{msg.message:X} to window {msg.hwnd} top={isTop}"); + // } + //} + } + } + //const int WS_CHILD = 0x40000000; + //Dictionary SeenHwnds = new(); + + private bool FilterMessage(ref MSG msg) + { + lock (_messageFiltersLock) + { + foreach (var filter in _messageFilters) + { + try + { + if (filter.PreFilterMessage(ref msg)) + { + return true; + } + } + catch (Exception ex) + { + OnUnhandledException(ex, ExceptionSource.MessageFilter); + } + } + } + + return false; + } + + /// + /// Post work to be executed on the UI thread. + /// Can be called from any thread. + /// + public void PostToUIThread(Action action) + { + if (InvokeRequired) + { + lock (_workQueueLock) + { + _workQueue.Enqueue(action); + } + + if (!_mainWindow.IsNull) + { + PInvoke.PostMessage(_mainWindow, WM_APP_INVOKE, 0, 0); + } + } + else + { + action(); + } + } + + /// + /// Posts a quit message to terminate the message loop. + /// + public void Quit(int exitCode = 0) + { + if (InvokeRequired) + { + PostToUIThread(() => + { + PInvoke.PostQuitMessage(exitCode); + }); + } + else + { + PInvoke.PostQuitMessage(exitCode); + } + } + + private void ProcessWorkQueue() + { + while (true) + { + Action? action; + lock (_workQueueLock) + { + if (_workQueue.Count == 0) + break; + action = _workQueue.Dequeue(); + } + + try + { + action?.Invoke(); + } + catch (Exception ex) + { + OnUnhandledException(ex, ExceptionSource.WorkQueue); + } + } + } + + /// + /// Raises the UnhandledException event. + /// + internal void OnUnhandledException(Exception exception, ExceptionSource source) + { + var args = new Win32MessagePumpExceptionEventArgs(exception, source); + UnhandledException?.Invoke(this, args); + + if (!args.Handled) + { + System.Diagnostics.Debug.WriteLine($"{source} exception: {exception}"); + } + } + + private static LRESULT WindowProc(HWND hwnd, uint msg, WPARAM wParam, LPARAM lParam) + { + if (msg == PInvoke.WM_DESTROY) + { + PInvoke.PostQuitMessage(0); + return new LRESULT(0); + } + + return PInvoke.DefWindowProc(hwnd, msg, wParam, lParam); + } + + public void Dispose() + { + if (_disposed) + return; + + _disposed = true; + + if (!_mainWindow.IsNull) + { + PInvoke.DestroyWindow(_mainWindow); + _mainWindow = HWND.Null; + } + + UnregisterWindowClass(); + } +} + +/// +/// SynchronizationContext implementation for Win32MessagePump that integrates +/// with async/await and other .NET frameworks. +/// +#if !NETFRAMEWORK +[SupportedOSPlatform("windows5.1.2600")] +#endif +internal sealed class Win32SynchronizationContext : SynchronizationContext +{ + private readonly Win32MessagePump _messagePump; + + public Win32SynchronizationContext(Win32MessagePump messagePump) + { + _messagePump = messagePump ?? throw new ArgumentNullException(nameof(messagePump)); + } + + /// + /// Dispatches an asynchronous message to the message pump thread. + /// + public override void Post(SendOrPostCallback d, object? state) + { + if (d == null) return; + + _messagePump.PostToUIThread(() => + { + try + { + d(state); + } + catch (Exception ex) + { + _messagePump.OnUnhandledException(ex, ExceptionSource.SynchronizationContext); + } + }); + } + + /// + /// Dispatches a synchronous message to the message pump thread. + /// This is not recommended for general use as it can cause deadlocks. + /// + public override void Send(SendOrPostCallback d, object? state) + { + if (d == null) return; + + if (!_messagePump.InvokeRequired) + { + // Already on the UI thread + try + { + d(state); + } + catch (Exception ex) + { + _messagePump.OnUnhandledException(ex, ExceptionSource.SynchronizationContext); + throw; + } + return; + } + + // Send is synchronous - we need to block until the callback completes + // This is dangerous and can cause deadlocks, but it's part of the contract + using var completed = new ManualResetEventSlim(false); + Exception? exception = null; + + _messagePump.PostToUIThread(() => + { + try + { + d(state); + } + catch (Exception ex) + { + exception = ex; + _messagePump.OnUnhandledException(ex, ExceptionSource.SynchronizationContext); + } + finally + { + completed.Set(); + } + }); + + completed.Wait(); + + if (exception != null) + { + throw new InvalidOperationException("Exception occurred in Send operation", exception); + } + } + + /// + /// Creates a copy of the synchronization context. + /// + public override SynchronizationContext CreateCopy() + { + return new Win32SynchronizationContext(_messagePump); + } +} + +/// +/// Defines a message filter interface that allows external code to participate +/// in the message loop processing, similar to WinForms' IMessageFilter. +/// +interface IWin32MessageFilter +{ + /// + /// Filters a message before it is dispatched. + /// + /// The message to filter. + /// true to filter the message and stop it from being dispatched; + /// false to allow the message to continue to the next filter or be dispatched. + bool PreFilterMessage(ref MSG winMsg); +} + +/// +/// Event args for unhandled exceptions in the message pump. +/// +public class Win32MessagePumpExceptionEventArgs : EventArgs +{ + public Win32MessagePumpExceptionEventArgs(Exception exception, ExceptionSource source) + { + Exception = exception; + Source = source; + } + + /// + /// Gets the exception that occurred. + /// + public Exception Exception { get; } + + /// + /// Gets the source where the exception occurred. + /// + public ExceptionSource Source { get; } + + /// + /// Gets or sets whether the exception has been handled. + /// If false, the exception will be logged to Debug output. + /// + public bool Handled { get; set; } +} + +/// +/// Indicates where an exception originated in the message pump. +/// +public enum ExceptionSource +{ + /// + /// Exception occurred in a message filter. + /// + MessageFilter, + + /// + /// Exception occurred in a work queue item. + /// + WorkQueue, + + /// + /// Exception occurred in the SynchronizationContext. + /// + SynchronizationContext +} diff --git a/src/NTwain/CompilerTypes.cs b/src/NTwain/Polyfills/CompilerTypes.cs similarity index 88% rename from src/NTwain/CompilerTypes.cs rename to src/NTwain/Polyfills/CompilerTypes.cs index 0164315..b444867 100644 --- a/src/NTwain/CompilerTypes.cs +++ b/src/NTwain/Polyfills/CompilerTypes.cs @@ -1,4 +1,5 @@ -using System; +#if NETFRAMEWORK +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -8,15 +9,10 @@ using System.ComponentModel; namespace System.Runtime.CompilerServices { -#if !NET5_0_OR_GREATER [EditorBrowsable(EditorBrowsableState.Never)] internal static class IsExternalInit {} -#endif // !NET5_0_OR_GREATER - -#if !NET7_0_OR_GREATER - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)] internal sealed class RequiredMemberAttribute : Attribute {} @@ -34,14 +30,11 @@ namespace System.Runtime.CompilerServices public const string RefStructs = nameof(RefStructs); public const string RequiredMembers = nameof(RequiredMembers); } - -#endif // !NET7_0_OR_GREATER } namespace System.Diagnostics.CodeAnalysis { -#if !NET7_0_OR_GREATER [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)] internal sealed class SetsRequiredMembersAttribute : Attribute {} -#endif -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/NTwain/Polyfills/OperatingSystem.cs b/src/NTwain/Polyfills/OperatingSystem.cs new file mode 100644 index 0000000..32ac904 --- /dev/null +++ b/src/NTwain/Polyfills/OperatingSystem.cs @@ -0,0 +1,103 @@ +#if NETFRAMEWORK +using System; +using System.Collections.Generic; + +namespace NTwain; + +/// +/// Nicety for old framework use to not have to use preprocessors. +/// +static class OperatingSystem +{ + static readonly bool _isWindows = Environment.OSVersion.Platform == PlatformID.Win32NT; + public static bool IsWindows() => _isWindows; + + static readonly bool _isLinux = Environment.OSVersion.Platform == PlatformID.Unix; + public static bool IsLinux() => _isLinux; + + static readonly bool _isMacOS = Environment.OSVersion.Platform == PlatformID.MacOSX; + public static bool IsMacOS() => _isMacOS; + + private struct VersionKey : IEquatable + { + public int Major; + public int Minor; + public int Build; + public int Revision; + + public VersionKey(int major, int minor, int build, int revision) + { + Major = major; + Minor = minor; + Build = build; + Revision = revision; + } + + public bool Equals(VersionKey other) + { + return Major == other.Major && Minor == other.Minor && Build == other.Build && Revision == other.Revision; + } + + public override bool Equals(object obj) + { + return obj is VersionKey other && Equals(other); + } + + public override int GetHashCode() + { + unchecked + { + int hash = 17; + hash = hash * 31 + Major; + hash = hash * 31 + Minor; + hash = hash * 31 + Build; + hash = hash * 31 + Revision; + return hash; + } + } + } + + private static readonly Dictionary _versionCache = new Dictionary(); + + public static bool IsWindowsVersionAtLeast(int major, int minor = 0, int build = 0, int revision = 0) + { + if (!IsWindows()) + return false; + + var key = new VersionKey(major, minor, build, revision); + if (!_versionCache.TryGetValue(key, out bool result)) + { + result = IsOSVersionAtLeast(major, minor, build, revision); + _versionCache[key] = result; + } + return result; + } + + private static bool IsOSVersionAtLeast(int major, int minor, int build, int revision) + { + Version current = Environment.OSVersion.Version; + + if (current.Major != major) + { + return current.Major > major; + } + if (current.Minor != minor) + { + return current.Minor > minor; + } + // Unspecified build component is to be treated as zero + int currentBuild = current.Build < 0 ? 0 : current.Build; + build = build < 0 ? 0 : build; + if (currentBuild != build) + { + return currentBuild > build; + } + + // Unspecified revision component is to be treated as zero + int currentRevision = current.Revision < 0 ? 0 : current.Revision; + revision = revision < 0 ? 0 : revision; + + return currentRevision >= revision; + } +} +#endif \ No newline at end of file diff --git a/src/NTwain/SourceEnableOption.cs b/src/NTwain/SourceEnableOption.cs new file mode 100644 index 0000000..73e6d4b --- /dev/null +++ b/src/NTwain/SourceEnableOption.cs @@ -0,0 +1,24 @@ +// this file tracks twain state and has methods that can change the twain state and +// manage data sources. + +namespace NTwain; + +/// +/// Options for enabling a data source. +/// +public enum SourceEnableOption +{ + /// + /// Start the transfer without showing the driver settings UI. + /// Progress indicator UI may still be shown. + /// + NoUI, + /// + /// Show the driver UI then start the transfer when user accepts. + /// + ShowUI, + /// + /// Show the driver UI but don't perform transfers (modify settings only). + /// + UIOnly +} diff --git a/src/NTwain/TWAINWorkingGroup/NativeMethods.cs b/src/NTwain/TWAINWorkingGroup/NativeMethods.cs index 3eba1c1..bad2643 100644 --- a/src/NTwain/TWAINWorkingGroup/NativeMethods.cs +++ b/src/NTwain/TWAINWorkingGroup/NativeMethods.cs @@ -161,7 +161,7 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryNullDest // ( -// ref TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY origin, // IntPtr zero, // DG dg, // DAT dat, @@ -172,7 +172,7 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryNullDest // ( -// ref TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY origin, // IntPtr zero, // DG dg, // DAT dat, @@ -183,7 +183,7 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryNullDest // ( -// ref TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY origin, // IntPtr zero, // DG dg, // DAT dat, @@ -194,7 +194,7 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryNullDest // ( -// ref TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY origin, // IntPtr zero, // DG dg, // DAT dat, @@ -205,7 +205,7 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryNullDest // ( -// ref TW_IDENTITY origin, +// TW_IDENTITY origin, // IntPtr zero, // DG dg, // DAT dat, @@ -216,7 +216,7 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryNullDest // ( -// ref TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX origin, // IntPtr zero, // DG dg, // DAT dat, @@ -227,7 +227,7 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryNullDest // ( -// ref TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX origin, // IntPtr zero, // DG dg, // DAT dat, @@ -251,8 +251,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntry // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -262,8 +262,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntry // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -273,8 +273,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntry // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -284,8 +284,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntry // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -295,8 +295,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntry // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -306,8 +306,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntry // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -317,8 +317,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntry // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -340,8 +340,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryAudioAudiofilexfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -351,8 +351,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryAudioAudiofilexfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -362,8 +362,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryAudioAudiofilexfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -373,8 +373,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryAudioAudiofilexfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -384,8 +384,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryAudioAudiofilexfer // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -395,8 +395,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryAudioAudiofilexfer // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -406,8 +406,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryAudioAudiofilexfer // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -428,8 +428,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryAudioAudioinfo // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -439,8 +439,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryAudioAudioinfo // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -450,8 +450,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryAudioAudioinfo // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -461,8 +461,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryAudioAudioinfo // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -472,8 +472,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryAudioAudioinfo // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -483,8 +483,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryAudioAudioinfo // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -494,8 +494,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryAudioAudioinfo // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -528,8 +528,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryCallback // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -539,8 +539,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryCallback // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -550,8 +550,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryCallback // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -561,8 +561,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryCallback // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -572,8 +572,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryCallback // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -583,7 +583,7 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryCallback // ( -// ref TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX origin, // IntPtr dest, // DG dg, // DAT dat, @@ -594,8 +594,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryCallback // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -603,8 +603,8 @@ // ); // public delegate UInt16 WindowsDsmEntryCallbackDelegate // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -612,8 +612,8 @@ // ); // public delegate UInt16 LinuxDsmEntryCallbackDelegate // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -621,8 +621,8 @@ // ); // public delegate UInt16 Linux020302Dsm64bitEntryCallbackDelegate // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -630,8 +630,8 @@ // ); // public delegate UInt16 MacosxDsmEntryCallbackDelegate // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -652,8 +652,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryCallback2 // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -663,8 +663,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryCallback2 // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -674,8 +674,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryCallback2 // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -685,8 +685,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryCallback2 // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -696,8 +696,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryCallback2 // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -707,7 +707,7 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryCallback2 // ( -// ref TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX origin, // IntPtr dest, // DG dg, // DAT dat, @@ -718,8 +718,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryCallback2 // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY des, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY des, // DG dg, // DAT dat, // MSG msg, @@ -727,8 +727,8 @@ // ); // private delegate UInt16 WindowsDsmEntryCallback2Delegate // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -736,8 +736,8 @@ // ); // private delegate UInt16 LinuxDsmEntryCallback2Delegate // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -745,8 +745,8 @@ // ); // private delegate UInt16 Linux020302Dsm64bitEntryCallback2Delegate // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -754,8 +754,8 @@ // ); // private delegate UInt16 MacosxDsmEntryCallback2Delegate // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -776,8 +776,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryCapability // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -787,8 +787,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryCapability // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -798,8 +798,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryCapability // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -809,8 +809,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryCapability // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -820,8 +820,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryCapability // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -831,8 +831,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryCapability // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -842,8 +842,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryCapability // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -864,8 +864,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryCustomdsdata // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -875,8 +875,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryCustomdsdata // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -886,8 +886,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryCustomdsdata // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -897,8 +897,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryCustomdsdata // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -908,8 +908,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryCustomdsdata // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -919,8 +919,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryCustomdsdata // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -930,8 +930,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryCustomdsdata // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -952,8 +952,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryDeviceevent // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -963,8 +963,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryDeviceevent // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -974,8 +974,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryDeviceevent // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -985,8 +985,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryDeviceevent // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -996,8 +996,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryDeviceevent // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -1007,8 +1007,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryDeviceevent // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -1018,8 +1018,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryDeviceevent // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -1040,8 +1040,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryEvent // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1051,8 +1051,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryEvent // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1062,8 +1062,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryEvent // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1073,8 +1073,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryEvent // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1084,8 +1084,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryEvent // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -1095,8 +1095,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryEvent // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -1106,8 +1106,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryEvent // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -1128,8 +1128,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryEntrypoint // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1139,8 +1139,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryEntrypoint // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1150,8 +1150,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryEntrypoint // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1161,8 +1161,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryEntrypoint // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1172,8 +1172,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryEntrypoint // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -1183,8 +1183,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryEntrypoint // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -1194,8 +1194,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryEntrypoint // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -1216,8 +1216,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryFilesystem // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1227,8 +1227,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryFilesystem // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1238,8 +1238,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryFilesystem // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1249,8 +1249,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryFilesystem // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1260,8 +1260,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryFilesystem // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -1271,8 +1271,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryFilesystem // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -1282,8 +1282,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryFilesystem // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -1304,89 +1304,89 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryIdentity // ( -// ref TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY origin, // IntPtr dest, // DG dg, // DAT dat, // MSG msg, -// ref TW_IDENTITY_LEGACY twidentity +// TW_IDENTITY_LEGACY twidentity // ); // [SuppressMessage("Microsoft.Interoperability", "CA1400:PInvokeEntryPointsShouldExist")] // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryIdentityState4 // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, -// ref TW_IDENTITY_LEGACY twidentity +// TW_IDENTITY_LEGACY twidentity // ); // [SuppressMessage("Microsoft.Interoperability", "CA1400:PInvokeEntryPointsShouldExist")] // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryIdentity // ( -// ref TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY origin, // IntPtr dest, // DG dg, // DAT dat, // MSG msg, -// ref TW_IDENTITY_LEGACY twidentity +// TW_IDENTITY_LEGACY twidentity // ); // [SuppressMessage("Microsoft.Interoperability", "CA1400:PInvokeEntryPointsShouldExist")] // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryIdentity // ( -// ref TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY origin, // IntPtr dest, // DG dg, // DAT dat, // MSG msg, -// ref TW_IDENTITY_LEGACY twidentity +// TW_IDENTITY_LEGACY twidentity // ); // [SuppressMessage("Microsoft.Interoperability", "CA1400:PInvokeEntryPointsShouldExist")] // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryIdentity // ( -// ref TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY origin, // IntPtr dest, // DG dg, // DAT dat, // MSG msg, -// ref TW_IDENTITY_LEGACY twidentity +// TW_IDENTITY_LEGACY twidentity // ); // [SuppressMessage("Microsoft.Interoperability", "CA1400:PInvokeEntryPointsShouldExist")] // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryIdentity // ( -// ref TW_IDENTITY_LINUX64 origin, +// TW_IDENTITY_LINUX64 origin, // IntPtr dest, // DG dg, // DAT dat, // MSG msg, -// ref TW_IDENTITY_LINUX64 twidentity +// TW_IDENTITY_LINUX64 twidentity // ); // [SuppressMessage("Microsoft.Interoperability", "CA1400:PInvokeEntryPointsShouldExist")] // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryIdentity // ( -// ref TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX origin, // IntPtr dest, // DG dg, // DAT dat, // MSG msg, -// ref TW_IDENTITY_MACOSX twidentity +// TW_IDENTITY_MACOSX twidentity // ); // [SuppressMessage("Microsoft.Interoperability", "CA1400:PInvokeEntryPointsShouldExist")] // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryIdentity // ( -// ref TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX origin, // IntPtr dest, // DG dg, // DAT dat, // MSG msg, -// ref TW_IDENTITY_MACOSX twidentity +// TW_IDENTITY_MACOSX twidentity // ); // /// @@ -1415,7 +1415,7 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryParent // ( -// ref TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY origin, // IntPtr dest, // DG dg, // DAT dat, @@ -1426,7 +1426,7 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryParent // ( -// ref TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY origin, // IntPtr dest, // DG dg, // DAT dat, @@ -1437,7 +1437,7 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryParent // ( -// ref TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY origin, // IntPtr dest, // DG dg, // DAT dat, @@ -1448,7 +1448,7 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryParent // ( -// ref TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY origin, // IntPtr dest, // DG dg, // DAT dat, @@ -1459,7 +1459,7 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryParent // ( -// ref TW_IDENTITY origin, +// TW_IDENTITY origin, // IntPtr dest, // DG dg, // DAT dat, @@ -1470,7 +1470,7 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryParent // ( -// ref TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX origin, // IntPtr dest, // DG dg, // DAT dat, @@ -1481,7 +1481,7 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryParent // ( -// ref TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX origin, // IntPtr dest, // DG dg, // DAT dat, @@ -1503,8 +1503,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryPassthru // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1514,8 +1514,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryPassthru // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1525,8 +1525,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryPassthru // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1536,8 +1536,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryPassthru // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1547,8 +1547,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryPassthru // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -1558,8 +1558,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryPassthru // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -1569,8 +1569,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryPassthru // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -1591,8 +1591,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryPendingxfers // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1602,8 +1602,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryPendingxfers // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1613,8 +1613,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryPendingxfers // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1624,8 +1624,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryPendingxfers // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1635,8 +1635,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryPendingxfers // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -1646,8 +1646,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryPendingxfers // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -1657,8 +1657,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryPendingxfers // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -1679,8 +1679,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntrySetupfilexfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1690,8 +1690,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntrySetupfilexfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1701,8 +1701,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntrySetupfilexfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1712,8 +1712,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntrySetupfilexfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1723,8 +1723,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntrySetupfilexfer // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -1734,8 +1734,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntrySetupfilexfer // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -1745,8 +1745,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntrySetupfilexfer // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -1767,8 +1767,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntrySetupmemxfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1778,8 +1778,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntrySetupmemxfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1789,8 +1789,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntrySetupmemxfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1800,8 +1800,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntrySetupmemxfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1811,8 +1811,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntrySetupmemxfer // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -1822,8 +1822,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntrySetupmemxfer // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -1833,8 +1833,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntrySetupmemxfer // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -1855,8 +1855,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryStatus // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1866,7 +1866,7 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryStatusState3 // ( -// ref TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY origin, // IntPtr dest, // DG dg, // DAT dat, @@ -1877,8 +1877,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryStatus // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1888,7 +1888,7 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryStatusState3 // ( -// ref TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY origin, // IntPtr dest, // DG dg, // DAT dat, @@ -1899,8 +1899,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryStatus // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1910,7 +1910,7 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryStatusState3 // ( -// ref TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY origin, // IntPtr dest, // DG dg, // DAT dat, @@ -1921,8 +1921,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryStatus // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -1932,7 +1932,7 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryStatusState3 // ( -// ref TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY origin, // IntPtr dest, // DG dg, // DAT dat, @@ -1943,8 +1943,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryStatus // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -1954,7 +1954,7 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryStatusState3 // ( -// ref TW_IDENTITY origin, +// TW_IDENTITY origin, // IntPtr dest, // DG dg, // DAT dat, @@ -1965,8 +1965,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryStatus // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -1976,7 +1976,7 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryStatusState3 // ( -// ref TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX origin, // IntPtr dest, // DG dg, // DAT dat, @@ -1987,8 +1987,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryStatus // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -1998,7 +1998,7 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryStatusState3 // ( -// ref TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX origin, // IntPtr dest, // DG dg, // DAT dat, @@ -2020,8 +2020,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryStatusutf8 // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2031,8 +2031,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryStatusutf8 // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2042,8 +2042,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryStatusutf8 // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2053,8 +2053,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryStatusutf8 // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2064,8 +2064,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryStatusutf8 // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -2075,8 +2075,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryStatusutf8 // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -2086,8 +2086,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryStatusutf8 // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -2108,8 +2108,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryTwaindirect // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2119,8 +2119,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryTwaindirect // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2130,8 +2130,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryTwaindirect // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2141,8 +2141,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryTwaindirect // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2152,8 +2152,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryTwaindirect // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -2163,8 +2163,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryTwaindirect // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -2174,8 +2174,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryTwaindirect // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -2196,8 +2196,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryUserinterface // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2207,8 +2207,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryUserinterface // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2218,8 +2218,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryUserinterface // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2229,8 +2229,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryUserinterface // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2240,8 +2240,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryUserinterface // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -2251,8 +2251,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryUserinterface // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -2262,8 +2262,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryUserinterface // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -2284,8 +2284,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryXfergroup // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2295,8 +2295,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryXfergroup // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2306,8 +2306,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryXfergroup // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2317,8 +2317,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryXfergroup // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2328,8 +2328,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryXfergroup // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -2339,8 +2339,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryXfergroup // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -2350,8 +2350,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryXfergroup // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -2372,8 +2372,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryAudiofilexfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2383,8 +2383,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryAudiofilexfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2394,8 +2394,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryAudiofilexfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2405,8 +2405,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryAudiofilexfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2416,8 +2416,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryAudiofilexfer // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -2427,8 +2427,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryAudiofilexfer // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -2438,8 +2438,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryAudiofilexfer // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -2460,8 +2460,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryAudionativexfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2471,8 +2471,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryAudionativexfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2482,8 +2482,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryAudionativexfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2493,8 +2493,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryAudionativexfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2504,8 +2504,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryAudionativexfer // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -2515,8 +2515,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryAudionativexfer // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -2526,8 +2526,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryAudionativexfer // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -2548,8 +2548,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryCiecolor // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2559,8 +2559,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryCiecolor // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2570,8 +2570,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryCiecolor // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2581,8 +2581,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryCiecolor // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2592,8 +2592,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryCiecolor // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -2603,8 +2603,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryCiecolor // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -2614,8 +2614,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryCiecolor // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -2636,8 +2636,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryExtimageinfo // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2647,8 +2647,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryExtimageinfo // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2658,8 +2658,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryExtimageinfo // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2669,8 +2669,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryExtimageinfo // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2680,8 +2680,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryExtimageinfo // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -2691,8 +2691,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryExtimageinfo // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -2702,8 +2702,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryExtimageinfo // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -2724,8 +2724,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryFilter // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2735,8 +2735,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryFilter // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2746,8 +2746,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryFilter // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2757,8 +2757,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryFilter // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2768,8 +2768,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryFilter // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -2779,8 +2779,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryFilter // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -2790,8 +2790,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryFilter // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -2812,8 +2812,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryGrayresponse // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2823,8 +2823,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryGrayresponse // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2834,8 +2834,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryGrayresponse // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2845,8 +2845,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryGrayresponse // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2856,8 +2856,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryGrayresponse // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -2867,8 +2867,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryGrayresponse // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -2878,8 +2878,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryGrayresponse // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -2900,8 +2900,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryIccprofile // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2911,8 +2911,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryIccprofile // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2922,8 +2922,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryIccprofile // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2933,8 +2933,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryIccprofile // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2944,8 +2944,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryIccprofile // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -2955,8 +2955,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryIccprofile // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -2966,8 +2966,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryIccprofile // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -2988,8 +2988,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryImagefilexfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -2999,8 +2999,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryImagefilexfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3010,8 +3010,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryImagefilexfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3021,8 +3021,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryImagefilexfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3032,8 +3032,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryImagefilexfer // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -3043,8 +3043,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryImagefilexfer // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -3054,8 +3054,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryImagefilexfer // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -3076,8 +3076,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryImageinfo // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3087,8 +3087,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryImageinfo // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3098,8 +3098,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryImageinfo // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3109,8 +3109,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryImageinfo // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3120,8 +3120,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryImageinfo // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -3131,8 +3131,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryImageinfo // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -3142,8 +3142,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryImageinfo // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -3164,8 +3164,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryImagelayout // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3175,8 +3175,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryImagelayout // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3186,8 +3186,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryImagelayout // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3197,8 +3197,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryImagelayout // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3208,8 +3208,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryImagelayout // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -3219,8 +3219,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryImagelayout // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -3230,8 +3230,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryImagelayout // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -3252,8 +3252,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryImagememfilexfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3263,8 +3263,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryImagememfilexfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3274,8 +3274,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryImagememfilexfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3285,8 +3285,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryImagememfilexfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3296,8 +3296,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryImagememfilexfer // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -3307,8 +3307,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryImagememfilexfer // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -3318,8 +3318,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryImagememfilexfer // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -3340,8 +3340,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryImagememxfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3351,8 +3351,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryImagememxfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3362,8 +3362,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryImagememxfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3373,8 +3373,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryImagememxfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3384,8 +3384,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryImagememxfer // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -3395,8 +3395,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryImagememxfer // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -3406,8 +3406,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryImagememxfer // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -3428,8 +3428,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryImagenativexfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3439,8 +3439,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryImagenativexfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3450,8 +3450,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryImagenativexfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3461,8 +3461,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryImagenativexfer // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3472,8 +3472,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryImagenativexfer // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -3483,8 +3483,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryImagenativexfer // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -3494,8 +3494,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryImagenativexfer // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -3516,8 +3516,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryJpegcompression // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3527,8 +3527,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryJpegcompression // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3538,8 +3538,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryJpegcompression // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3549,8 +3549,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryJpegcompression // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3560,8 +3560,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryJpegcompression // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -3571,8 +3571,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryJpegcompression // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -3582,8 +3582,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryJpegcompression // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -3604,8 +3604,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryMetrics // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3615,8 +3615,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryMetrics // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3626,8 +3626,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryMetrics // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3637,8 +3637,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryMetrics // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3648,8 +3648,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryMetrics // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -3659,8 +3659,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryMetrics // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -3670,8 +3670,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryMetrics // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -3692,8 +3692,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryPalette8 // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3703,8 +3703,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryPalette8 // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3714,8 +3714,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryPalette8 // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3725,8 +3725,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryPalette8 // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3736,8 +3736,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryPalette8 // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -3747,8 +3747,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryPalette8 // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -3758,8 +3758,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryPalette8 // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -3780,8 +3780,8 @@ // [DllImport("twain_32.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwain32DsmEntryRgbresponse // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3791,8 +3791,8 @@ // [DllImport("twaindsm.dll", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 WindowsTwaindsmDsmEntryRgbresponse // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3802,8 +3802,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 LinuxDsmEntryRgbresponse // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3813,8 +3813,8 @@ // [DllImport("/usr/local/lib64/libtwaindsm.so", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux64DsmEntryRgbresponse // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -3824,8 +3824,8 @@ // [DllImport("/usr/local/lib/libtwaindsm.so.2.3.2", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 Linux020302Dsm64bitEntryRgbresponse // ( -// ref TW_IDENTITY origin, -// ref TW_IDENTITY dest, +// TW_IDENTITY origin, +// TW_IDENTITY dest, // DG dg, // DAT dat, // MSG msg, @@ -3835,8 +3835,8 @@ // [DllImport("/System/Library/Frameworks/framework/TWAIN", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwainDsmEntryRgbresponse // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, @@ -3846,8 +3846,8 @@ // [DllImport("/Library/Frameworks/TWAINDSM.framework/TWAINDSM", EntryPoint = "DSM_Entry", CharSet = CharSet.Ansi)] // internal static extern UInt16 MacosxTwaindsmDsmEntryRgbresponse // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, diff --git a/src/NTwain/TWAINWorkingGroup/TWAIN.cs b/src/NTwain/TWAINWorkingGroup/TWAIN.cs index 6e94bb6..7b8314f 100644 --- a/src/NTwain/TWAINWorkingGroup/TWAIN.cs +++ b/src/NTwain/TWAINWorkingGroup/TWAIN.cs @@ -2822,7 +2822,7 @@ // /// A TWAIN structure // /// A CSV string of the TWAIN structure // /// True if the conversion is successful -// public static bool CsvToIdentity(ref TW_IDENTITY a_twidentity, string a_szIdentity) +// public static bool CsvToIdentity(TW_IDENTITY a_twidentity, string a_szIdentity) // { // // Init stuff... // a_twidentity = default(TW_IDENTITY); @@ -7486,7 +7486,7 @@ // ); // } // [PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust", Unrestricted = false)] -// public STS DatIdentity(DG a_dg, MSG a_msg, ref TW_IDENTITY a_twidentity) +// public STS DatIdentity(DG a_dg, MSG a_msg, TW_IDENTITY a_twidentity) // { // STS sts; @@ -13791,8 +13791,8 @@ // /// TWAIN status // private UInt16 WindowsDsmEntryCallbackProxy // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -13815,8 +13815,8 @@ // /// TWAIN status // private UInt16 LinuxDsmEntryCallbackProxy // ( -// ref TW_IDENTITY_LEGACY origin, -// ref TW_IDENTITY_LEGACY dest, +// TW_IDENTITY_LEGACY origin, +// TW_IDENTITY_LEGACY dest, // DG dg, // DAT dat, // MSG msg, @@ -13839,8 +13839,8 @@ // /// TWAIN status // private UInt16 MacosxDsmEntryCallbackProxy // ( -// ref TW_IDENTITY_MACOSX origin, -// ref TW_IDENTITY_MACOSX dest, +// TW_IDENTITY_MACOSX origin, +// TW_IDENTITY_MACOSX dest, // DG dg, // DAT dat, // MSG msg, diff --git a/src/NTwain/TransferCanceledEventArgs.cs b/src/NTwain/TransferCanceledEventArgs.cs deleted file mode 100644 index 462148d..0000000 --- a/src/NTwain/TransferCanceledEventArgs.cs +++ /dev/null @@ -1,10 +0,0 @@ -using NTwain.Data; -using System; - -namespace NTwain -{ - public class TransferCanceledEventArgs : EventArgs - { - - } -} \ No newline at end of file diff --git a/src/NTwain/TransferErrorEventArgs.cs b/src/NTwain/TransferErrorEventArgs.cs deleted file mode 100644 index 3d56341..0000000 --- a/src/NTwain/TransferErrorEventArgs.cs +++ /dev/null @@ -1,47 +0,0 @@ -using NTwain.Data; -using System; - -namespace NTwain -{ - /// - /// Contains TWAIN codes and source status when an error is encountered during transfer. - /// - public class TransferErrorEventArgs : EventArgs - { - /// - /// Initializes a new instance of the class. - /// - /// The error. - public TransferErrorEventArgs(Exception error) - { - Exception = error; - } - - /// - /// Initializes a new instance of the class. - /// - /// The code. - /// Additional status info from TWAIN. - public TransferErrorEventArgs(STS code, string? info) - { - Code = code; - Info = info; - } - - /// - /// Gets the return code or condition code from the transfer. - /// - public STS Code { get; private set; } - - /// - /// Gets the additional status info from TWAIN. - /// - public string? Info { get; private set; } - - /// - /// Gets the exception if the error is from some exception - /// and not from TWAIN. - /// - public Exception? Exception { get; private set; } - } -} diff --git a/src/NTwain/TransferLoopThread.Logic.cs b/src/NTwain/TransferLoopThread.Logic.cs new file mode 100644 index 0000000..75ef10b --- /dev/null +++ b/src/NTwain/TransferLoopThread.Logic.cs @@ -0,0 +1,553 @@ +using Microsoft.Extensions.Logging; +using NTwain.Data; +using NTwain.Events; +using NTwain.Imaging; +using NTwain.Triplets; +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading; + +namespace NTwain; + +// this file contains the actual transfer loop logic, not bogged down with thread handling. + +partial class TransferLoopThread +{ + struct XferMechs + { + public TWSX ImageMech; + public TWSX AudioMech; + } + + XferMechs DetermineTransferMechs() + { + // don't think there are any actual audio twain devices so this is mostly theoretical + var hasAudio = DGControl.XferGroup.Get(_twain.AppIdentity, _twain.CurrentSource!, out DG xferType) == TWRC.SUCCESS && + xferType.HasFlag(DG.AUDIO); + + var imgMech = _twain.Caps.ICAP_XFERMECH.GetCurrent().FirstOrDefault(); + var audioMech = hasAudio ? _twain.Caps.ACAP_XFERMECH.GetCurrent().FirstOrDefault() : TWSX.NATIVE; + + return new XferMechs() { ImageMech = imgMech, AudioMech = audioMech }; + } + + STS EnterTransferLoop() + { + _twain.State = STATE.S6; + + // initial info gathering + var xferMechs = DetermineTransferMechs(); + if (_twain.Logger.IsEnabled(LogLevel.Trace)) + _twain.Logger.LogTrace("Determined transfer mech for image: {iMech}, audio: {aMech}.", xferMechs.ImageMech, xferMechs.AudioMech); + + string phase = ""; + + TW_PENDINGXFERS pending = TW_PENDINGXFERS.DONTCARE(); + var sts = _twain.WrapInSTS(DGControl.PendingXfers.Get(_twain.AppIdentity, _twain.CurrentSource!, ref pending)); + if (sts.RC != TWRC.SUCCESS) + { + phase = "PendingXfers.Get"; + var args = new TransferErrorEventArgs(sts, phase); + _twain.RaiseTransferError(args); + return sts; + } + + // test making this reusable + var readyArgs = new TransferReadyEventArgs(_twain, xferMechs.ImageMech, xferMechs.AudioMech); + + while (sts.RC == TWRC.SUCCESS && pending.Count != 0) + { + // give app chance to cancel + readyArgs.UpdatePending(ref pending); + _twain.RaiseTransferReady(readyArgs); + + if (readyArgs.Cancel == CancelType.EndNow || CloseDsRequested) + { + sts = ForceEndTransfer(); + } + else if (readyArgs.Cancel == CancelType.SkipCurrent) + { + pending = TW_PENDINGXFERS.DONTCARE(); + sts = _twain.WrapInSTS(DGControl.PendingXfers.EndXfer(_twain.AppIdentity, _twain.CurrentSource!, ref pending)); + if (sts.RC == TWRC.SUCCESS) + { + if (readyArgs.XferType == XferType.Audio) + { + _twain.State = STATE.S6; + } + else + { + _twain.State = pending.Count == 0 ? STATE.S5 : STATE.S6; + } + } + } + else + { + if (readyArgs.Cancel == CancelType.Graceful) + { + // ignore rc in this and continue transfer as normal + pending = TW_PENDINGXFERS.DONTCARE(); + DGControl.PendingXfers.StopFeeder(_twain.AppIdentity, _twain.CurrentSource!, ref pending); + } + + try + { + if (readyArgs.XferType == XferType.Audio) + { + switch (xferMechs.AudioMech) + { + case TWSX.NATIVE: + phase = "TransferNativeAudio"; + sts = TransferNativeAudio(ref pending); + break; + case TWSX.FILE: + phase = "TransferFileAudio"; + sts = TransferFileAudio(ref pending); + break; + } + } + else + { + switch (xferMechs.ImageMech) + { + case TWSX.NATIVE: + phase = "TransferNativeImage"; + sts = TransferNativeImage(ref pending); + break; + case TWSX.FILE: + phase = "TransferFileImage"; + sts = TransferFileImage(ref pending); + break; + case TWSX.MEMORY: + phase = "TransferMemoryImage"; + sts = TransferMemoryImage(ref pending); + break; + case TWSX.MEMFILE: + phase = "TransferMemoryFileImage"; + sts = TransferMemoryFileImage(ref pending); + break; + } + } + + } + catch (Exception ex) + { + _twain.RaiseTransferError(new TransferErrorEventArgs(ex, phase)); + } + HandleTransferResult(ref sts, out bool exitTransferLoop); + if (exitTransferLoop) break; + } + } + return sts; + } + + STS ForceEndTransfer() + { + var pending = TW_PENDINGXFERS.DONTCARE(); + var sts = _twain.WrapInSTS(DGControl.PendingXfers.EndXfer(_twain.AppIdentity, _twain.CurrentSource!, ref pending)); + pending = TW_PENDINGXFERS.DONTCARE(); + sts = _twain.WrapInSTS(DGControl.PendingXfers.Reset(_twain.AppIdentity, _twain.CurrentSource!, ref pending)); + if (sts.RC == TWRC.SUCCESS) _twain.State = STATE.S5; + return sts; + } + + private void HandleTransferResult(ref STS sts, out bool exitTransferLoop) + { + exitTransferLoop = false; + switch (sts.RC) + { + case TWRC.SUCCESS: + case TWRC.XFERDONE: + // do nothing + break; + case TWRC.CANCEL: + // might eventually have option to cancel this or all like transfer ready + sts = ForceEndTransfer(); + exitTransferLoop = true; + break; + default: + // TODO: raise error event + switch (sts.STATUS.ConditionCode) + { + case TWCC.SEQERROR: + // special break down to state 5 + sts = ForceEndTransfer(); + exitTransferLoop = true; + break; + case TWCC.DAMAGEDCORNER: + case TWCC.DOCTOODARK: + case TWCC.DOCTOOLIGHT: + case TWCC.FOCUSERROR: + case TWCC.NOMEDIA: + case TWCC.PAPERDOUBLEFEED: + case TWCC.PAPERJAM: + var pending = TW_PENDINGXFERS.DONTCARE(); + sts = _twain.WrapInSTS(DGControl.PendingXfers.EndXfer(_twain.AppIdentity, _twain.CurrentSource!, ref pending)); + break; + case TWCC.OPERATIONERROR: + var indicators = _twain.Caps.CAP_INDICATORS.GetCurrent().FirstOrDefault(); + if (_twain.EnabledWithOption == SourceEnableOption.NoUI && indicators == TW_BOOL.False) + { + // todo: alert user and drop to S4 + sts = ForceEndTransfer(); + exitTransferLoop = true; + } + break; + } + break; + } + } + + private STS TransferNativeAudio(ref TW_PENDINGXFERS pending) + { + IntPtr dataPtr = IntPtr.Zero; + IntPtr lockedPtr = IntPtr.Zero; + try + { + var sts = _twain.WrapInSTS(DGAudio.AudioNativeXfer.Get(_twain.AppIdentity, _twain.CurrentSource!, out dataPtr)); + if (sts.RC == TWRC.XFERDONE) + { + _twain.State = STATE.S7; + lockedPtr = _twain.MemoryManager.Lock(dataPtr); + BufferedData? data = default; + + // TODO: don't know how to read wav/aiff from pointer yet + + if (data != null) + { + try + { + DGAudio.AudioInfo.Get(_twain.AppIdentity, _twain.CurrentSource!, out TW_AUDIOINFO info); + var args = new TransferredEventArgs(info, data); + _twain.RaiseTransferred(args); + } + catch + { + data.Dispose(); + } + } + } + + pending = TW_PENDINGXFERS.DONTCARE(); + sts = _twain.WrapInSTS(DGControl.PendingXfers.EndXfer(_twain.AppIdentity, _twain.CurrentSource!, ref pending)); + if (sts.RC == TWRC.SUCCESS) + { + _twain.State = STATE.S6; + } + return sts; + } + finally + { + if (lockedPtr != IntPtr.Zero) _twain.MemoryManager.Unlock(lockedPtr); + if (dataPtr != IntPtr.Zero) _twain.MemoryManager.Free(dataPtr); + } + } + + private STS TransferFileAudio(ref TW_PENDINGXFERS pending) + { + // assuming user already configured the transfer in transferready event, + // get what will be transferred + var rc = DGControl.SetupFileXfer.Get(_twain.AppIdentity, _twain.CurrentSource!, out TW_SETUPFILEXFER fileSetup); + if (rc != TWRC.SUCCESS) return _twain.WrapInSTS(rc); + + // and just start it + var sts = _twain.WrapInSTS(DGAudio.AudioFileXfer.Get(_twain.AppIdentity, _twain.CurrentSource!)); + + if (sts.RC == TWRC.XFERDONE) + { + _twain.State = STATE.S7; + try + { + DGAudio.AudioInfo.Get(_twain.AppIdentity, _twain.CurrentSource!, out TW_AUDIOINFO info); + var args = new TransferredEventArgs(info, fileSetup); + _twain.RaiseTransferred(args); + } + catch { } + + pending = TW_PENDINGXFERS.DONTCARE(); + sts = _twain.WrapInSTS(DGControl.PendingXfers.EndXfer(_twain.AppIdentity, _twain.CurrentSource!, ref pending)); + if (sts.RC == TWRC.SUCCESS) + { + _twain.State = STATE.S6; + } + } + return sts; + } + + private STS TransferNativeImage(ref TW_PENDINGXFERS pending) + { + IntPtr dataPtr = IntPtr.Zero; + IntPtr lockedPtr = IntPtr.Zero; + try + { + DGImage.ImageInfo.Get(_twain.AppIdentity, _twain.CurrentSource!, out TW_IMAGEINFO info); + var sts = _twain.WrapInSTS(DGImage.ImageNativeXfer.Get(_twain.AppIdentity, _twain.CurrentSource!, out dataPtr)); + if (sts.RC == TWRC.XFERDONE) + { + _twain.State = STATE.S7; + lockedPtr = _twain.MemoryManager.Lock(dataPtr); + BufferedData? data = default; + + if (ImageTools.IsDib(lockedPtr)) + { + data = ImageTools.GetBitmapData(lockedPtr); + } + else if (ImageTools.IsTiff(lockedPtr)) + { + data = ImageTools.GetTiffData(lockedPtr); + } + else + { + // PicHandle? + // don't support more formats :( + } + + if (data != null) + { + try + { + // some sources do not support getting image info in state 7 so + // it's up there in the beginning now. + var args = new TransferredEventArgs(_twain, info, null, data); + _twain.RaiseTransferred(args); + } + catch + { + data.Dispose(); + } + } + + + pending = TW_PENDINGXFERS.DONTCARE(); + sts = _twain.WrapInSTS(DGControl.PendingXfers.EndXfer(_twain.AppIdentity, _twain.CurrentSource!, ref pending)); + if (sts.RC == TWRC.SUCCESS) + { + _twain.State = pending.Count == 0 ? STATE.S5 : STATE.S6; + } + } + return sts; + } + finally + { + if (lockedPtr != IntPtr.Zero) _twain.MemoryManager.Unlock(lockedPtr); + if (dataPtr != IntPtr.Zero) _twain.MemoryManager.Free(dataPtr); + } + } + + private STS TransferFileImage(ref TW_PENDINGXFERS pending) + { + // TODO: verify this still works + + // assuming user already configured the transfer in transferready event, + // get what will be transferred + DGControl.SetupFileXfer.Get(_twain.AppIdentity, _twain.CurrentSource!, out TW_SETUPFILEXFER fileSetup); + // and just start it + + int tries = 0; + RETRY: + var sts = _twain.WrapInSTS(DGImage.ImageFileXfer.Get(_twain.AppIdentity, _twain.CurrentSource!)); + + if (sts.RC == TWRC.XFERDONE) + { + _twain.State = STATE.S7; + try + { + DGImage.ImageInfo.Get(_twain.AppIdentity, _twain.CurrentSource!, out TW_IMAGEINFO info); + var args = new TransferredEventArgs(_twain, info, fileSetup, default); + _twain.RaiseTransferred(args); + } + catch { } + + pending = TW_PENDINGXFERS.DONTCARE(); + sts = _twain.WrapInSTS(DGControl.PendingXfers.EndXfer(_twain.AppIdentity, _twain.CurrentSource!, ref pending)); + if (sts.RC == TWRC.SUCCESS) + { + _twain.State = pending.Count == 0 ? STATE.S5 : STATE.S6; + } + } + else + { + // sometimes it errors only due to timing so wait a bit and try again + if (sts.RC == TWRC.FAILURE && (sts.ConditionCode == TWCC.None || sts.ConditionCode == TWCC.SEQERROR)) + { + if (tries++ < 3) + { + _twain.Logger.LogDebug("Using fileXfer timing workaround try {Tries}.", tries); + Thread.Sleep(500); + goto RETRY; + } + } + else + { + Debugger.Break(); + } + } + return sts; + } + + private STS TransferMemoryImage(ref TW_PENDINGXFERS pending) + { + // TODO: build the image from strips before firing off transferred event + + + var rc = DGControl.SetupMemXfer.Get(_twain.AppIdentity, _twain.CurrentSource!, out TW_SETUPMEMXFER memSetup); + if (rc != TWRC.SUCCESS) return _twain.WrapInSTS(rc); + rc = DGImage.ImageInfo.Get(_twain.AppIdentity, _twain.CurrentSource!, out TW_IMAGEINFO info); + if (rc != TWRC.SUCCESS) return _twain.WrapInSTS(rc); + rc = DGImage.ImageLayout.Get(_twain.AppIdentity, _twain.CurrentSource!, out TW_IMAGELAYOUT layout); + if (rc != TWRC.SUCCESS) return _twain.WrapInSTS(rc); + + uint buffSize = memSetup.DetermineBufferSize(); + var memPtr = _twain.MemoryManager.Alloc(buffSize); + + TW_IMAGEMEMXFER memXfer = TW_IMAGEMEMXFER.DONTCARE(); + TW_IMAGEMEMXFER_MACOSX memXferOSX = TW_IMAGEMEMXFER_MACOSX.DONTCARE(); + memXfer.Memory = new TW_MEMORY + { + Flags = (uint)(TWMF.APPOWNS | TWMF.POINTER), + Length = buffSize, + TheMem = memPtr + }; + memXferOSX.Memory = memXfer.Memory; + + byte[] dotnetBuff = BufferedData.MemPool.Rent((int)buffSize); + try + { + do + { + rc = TWPlatform.IsMacOSX ? + DGImage.ImageMemXfer.Get(_twain.AppIdentity, _twain.CurrentSource!, ref memXferOSX) : + DGImage.ImageMemXfer.Get(_twain.AppIdentity, _twain.CurrentSource!, ref memXfer); + + if (rc == TWRC.SUCCESS || rc == TWRC.XFERDONE) + { + try + { + var written = TWPlatform.IsMacOSX ? + memXferOSX.BytesWritten : memXfer.BytesWritten; + + IntPtr lockedPtr = _twain.MemoryManager.Lock(memPtr); + + // assemble! + + //Marshal.Copy(lockedPtr, dotnetBuff, 0, (int)written); + //outStream.Write(dotnetBuff, 0, (int)written); + } + finally + { + _twain.MemoryManager.Unlock(memPtr); + } + } + } while (rc == TWRC.SUCCESS); + } + finally + { + if (memPtr != IntPtr.Zero) _twain.MemoryManager.Free(memPtr); + BufferedData.MemPool.Return(dotnetBuff); + } + + + if (rc == TWRC.XFERDONE) + { + try + { + DGImage.ImageInfo.Get(_twain.AppIdentity, _twain.CurrentSource!, out info); + //var args = new DataTransferredEventArgs(info, null, outStream.ToArray()); + //DataTransferred?.Invoke(this, args); + } + catch { } + + pending = TW_PENDINGXFERS.DONTCARE(); + var sts = _twain.WrapInSTS(DGControl.PendingXfers.EndXfer(_twain.AppIdentity, _twain.CurrentSource!, ref pending)); + if (sts.RC == TWRC.SUCCESS) + { + _twain.State = pending.Count == 0 ? STATE.S5 : STATE.S6; + } + return sts; + } + return _twain.WrapInSTS(rc); + } + + private STS TransferMemoryFileImage(ref TW_PENDINGXFERS pending) + { + // TODO: verify this still works + + var rc = DGControl.SetupFileXfer.Get(_twain.AppIdentity, _twain.CurrentSource!, out TW_SETUPFILEXFER fileSetup); + if (rc != TWRC.SUCCESS) return _twain.WrapInSTS(rc); + rc = DGControl.SetupMemXfer.Get(_twain.AppIdentity, _twain.CurrentSource!, out TW_SETUPMEMXFER memSetup); + if (rc != TWRC.SUCCESS) return _twain.WrapInSTS(rc); + + uint buffSize = memSetup.DetermineBufferSize(); + var memPtr = _twain.MemoryManager.Alloc(buffSize); + + TW_IMAGEMEMXFER memXfer = TW_IMAGEMEMXFER.DONTCARE(); + TW_IMAGEMEMXFER_MACOSX memXferOSX = TW_IMAGEMEMXFER_MACOSX.DONTCARE(); + memXfer.Memory = new TW_MEMORY + { + Flags = (uint)(TWMF.APPOWNS | TWMF.POINTER), + Length = buffSize, + TheMem = memPtr + }; + memXferOSX.Memory = memXfer.Memory; + + // TODO: how to get actual file size before hand? Is it imagelayout? + // otherwise will just write to stream with lots of copies + byte[] dotnetBuff = BufferedData.MemPool.Rent((int)buffSize); + using var outStream = new MemoryStream(); + try + { + do + { + rc = TWPlatform.IsMacOSX ? + DGImage.ImageMemFileXfer.Get(_twain.AppIdentity, _twain.CurrentSource!, ref memXferOSX) : + DGImage.ImageMemFileXfer.Get(_twain.AppIdentity, _twain.CurrentSource!, ref memXfer); + + if (rc == TWRC.SUCCESS || rc == TWRC.XFERDONE) + { + try + { + var written = TWPlatform.IsMacOSX ? + memXferOSX.BytesWritten : memXfer.BytesWritten; + + IntPtr lockedPtr = _twain.MemoryManager.Lock(memPtr); + Marshal.Copy(lockedPtr, dotnetBuff, 0, (int)written); + outStream.Write(dotnetBuff, 0, (int)written); + } + finally + { + _twain.MemoryManager.Unlock(memPtr); + } + } + } while (rc == TWRC.SUCCESS); + } + finally + { + if (memPtr != IntPtr.Zero) _twain.MemoryManager.Free(memPtr); + BufferedData.MemPool.Return(dotnetBuff); + } + + if (rc == TWRC.XFERDONE) + { + try + { + DGImage.ImageInfo.Get(_twain.AppIdentity, _twain.CurrentSource!, out TW_IMAGEINFO info); + // ToArray bypasses the XferMemPool but I guess this will have to do for now + var args = new TransferredEventArgs(_twain, info, fileSetup, new BufferedData(outStream.ToArray(), (int)outStream.Length, false)); + _twain.RaiseTransferred(args); + } + catch { } + + pending = TW_PENDINGXFERS.DONTCARE(); + var sts = _twain.WrapInSTS(DGControl.PendingXfers.EndXfer(_twain.AppIdentity, _twain.CurrentSource!, ref pending)); + if (sts.RC == TWRC.SUCCESS) + { + _twain.State = pending.Count == 0 ? STATE.S5 : STATE.S6; + } + return sts; + } + return _twain.WrapInSTS(rc); + } +} diff --git a/src/NTwain/TransferLoopThread.cs b/src/NTwain/TransferLoopThread.cs new file mode 100644 index 0000000..74684bb --- /dev/null +++ b/src/NTwain/TransferLoopThread.cs @@ -0,0 +1,99 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Threading; + +namespace NTwain; + +/// +/// Contains logic for handling the transfer loop of data from a TWAIN source +/// in another thread. +/// +partial class TransferLoopThread : IDisposable +{ + readonly Thread _transferThread; + readonly CancellationTokenSource _transferThreadEnder = new(); + readonly ManualResetEventSlim _transferReady = new(false); + readonly TwainAppSession _twain; + + public TransferLoopThread(TwainAppSession twain) + { + _twain = twain; + _transferThread = new(ThreadWork) + { + IsBackground = true + }; + if (OperatingSystem.IsWindowsVersionAtLeast(6, 0, 6000)) + { + // is this necessary? who knows + _transferThread.SetApartmentState(ApartmentState.STA); + } + _transferThread.Start(); + } + + public bool CloseDsRequested { get; internal set; } + public bool IsTransferring { get; private set; } + + public void NotifyTransferReady(bool ready) + { + if (ready) + { + _transferReady.Set(); + } + else + { + _transferReady.Reset(); + } + } + + private void ThreadWork() + { + if (_twain.Logger.IsEnabled(LogLevel.Trace)) + _twain.Logger.LogTrace("[thread {ThreadId}] Transfer thread started.", Environment.CurrentManagedThreadId); + try + { + while (!_transferThreadEnder.Token.IsCancellationRequested) + { + _transferReady.Wait(_transferThreadEnder.Token); + if (_twain.Logger.IsEnabled(LogLevel.Trace)) + _twain.Logger.LogTrace("[thread {ThreadId}] Transfer thread woke up to do transfer.", Environment.CurrentManagedThreadId); + + IsTransferring = true; + try + { + EnterTransferLoop(); + } + catch (Exception ex) + { + + } + finally + { + _transferReady.Reset(); + _twain.DisableSource(); + + IsTransferring = false; + } + } + } + catch (OperationCanceledException) + { + // Clean shutdown + } + if (_twain.Logger.IsEnabled(LogLevel.Trace)) + _twain.Logger.LogTrace("[thread {ThreadId}] Transfer thread ending.", Environment.CurrentManagedThreadId); + } + + bool _disposed = false; + public void Dispose() + { + if (_disposed) return; + + _disposed = true; + + _transferThreadEnder.Cancel(); + _transferThread.Join(TimeSpan.FromSeconds(5)); + + _transferReady.Dispose(); + _transferThreadEnder.Dispose(); + } +} diff --git a/src/NTwain/TransferReadyEventArgs.cs b/src/NTwain/TransferReadyEventArgs.cs deleted file mode 100644 index 70e0ed2..0000000 --- a/src/NTwain/TransferReadyEventArgs.cs +++ /dev/null @@ -1,114 +0,0 @@ -using NTwain.Data; -using System; - -namespace NTwain -{ - /// - /// Contains event data when a data transfer is ready to be processed. - /// - public class TransferReadyEventArgs : EventArgs - { - public TransferReadyEventArgs(TwainAppSession twain, TWSX imgXferMech, TWSX audXferMech, int pendingCount, TWEJ endOfJobFlag) - { - _twain = twain; - ImgXferMech = imgXferMech; - AudXferMech = audXferMech; - PendingCount = pendingCount; - EndOfJobFlag = endOfJobFlag; - } - - /// - /// Gets or sets whether to cancel the capture phase. - /// - public CancelType Cancel { get; set; } - - /// - /// Gets the end of job flag value for this transfer if job control is enabled. - /// - public TWEJ EndOfJobFlag { get; } - - /// - /// Gets the current transfer mech if working with images. - /// - public TWSX ImgXferMech { get; } - - /// - /// Gets the current transfer mech if working with audio. - /// - public TWSX AudXferMech { get; } - - /// - /// Gets the known pending transfer count. This may not be appilicable - /// for certain scanning modes. - /// - public int PendingCount { get; private set; } - - private readonly TwainAppSession _twain; - - /// - /// If the transfer mech is file-related, - /// setup the file transfer options here. - /// - /// - /// - public STS SetupFileTransfer(ref TW_SETUPFILEXFER fileXfer) - { - return _twain.SetFileXfer(ref fileXfer); - } - - /// - /// Gets the ext image info at this state for Kodak devices. Use any utility methods on it - /// to read the data. Remember to call - /// when done. - /// - /// Container to query. Can be created with - /// - public STS GetExtendedImageInfo(ref TW_EXTIMAGEINFO container) - { - if (_twain == null) return default; - return _twain.GetExtendedImageInfoSpecial(ref container); - } - - //TW_IMAGEINFO? _imgInfo; - ///// - ///// Gets the tentative image information for the current transfer if applicable. - ///// This may differ from the final image depending on the transfer mode used (mostly when doing mem xfer). - ///// - //public TW_IMAGEINFO? PendingImageInfo - //{ - // get - // { - // // only get it if requested since it could be slow - // if (!_imgInfo.HasValue) - // { - // if (_twain.GetImageInfo(out TW_IMAGEINFO info).RC == TWRC.SUCCESS) - // { - // _imgInfo = info; - // } - // } - // return _imgInfo; - // } - //} - - } - - public enum CancelType - { - /// - /// No cancel. - /// - None, - /// - /// Skips current transfer. - /// - SkipCurrent, - /// - /// Stops feeder but continue receiving already scanned images in the app. - /// - Graceful, - /// - /// Stops feeder and discard any pending images. - /// - EndNow - } -} diff --git a/src/NTwain/Triplets/AudioDATs/AudioFileXfer.cs b/src/NTwain/Triplets/AudioDATs/AudioFileXfer.cs index 50eff2a..91145a2 100644 --- a/src/NTwain/Triplets/AudioDATs/AudioFileXfer.cs +++ b/src/NTwain/Triplets/AudioDATs/AudioFileXfer.cs @@ -2,44 +2,41 @@ using NTwain.DSM; using System; -namespace NTwain.Triplets.AudioDATs -{ - /// - /// Contains calls used with and . - /// - public class AudioFileXfer - { - public TWRC Get(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds) - => DoIt(ref app, ref ds, MSG.GET); +namespace NTwain.Triplets.AudioDATs; - static TWRC DoIt(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, MSG msg) +/// +/// Contains calls used with and . +/// +public class AudioFileXfer +{ + public TWRC Get(TWIdentityWrapper app, TWIdentityWrapper ds) + => DoIt(app, ds, MSG.GET); + + static TWRC DoIt(TWIdentityWrapper app, TWIdentityWrapper ds, MSG msg) { - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.AUDIO, DAT.AUDIOFILEXFER, msg, IntPtr.Zero); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.AUDIO, DAT.AUDIOFILEXFER, msg, IntPtr.Zero); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.AUDIO, DAT.AUDIOFILEXFER, msg, IntPtr.Zero); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.AUDIO, DAT.AUDIOFILEXFER, msg, IntPtr.Zero); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.AUDIO, DAT.AUDIOFILEXFER, msg, IntPtr.Zero); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.AUDIO, DAT.AUDIOFILEXFER, msg, IntPtr.Zero); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.AUDIO, DAT.AUDIOFILEXFER, msg, IntPtr.Zero); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.AUDIO, DAT.AUDIOFILEXFER, msg, IntPtr.Zero); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/AudioDATs/AudioInfo.cs b/src/NTwain/Triplets/AudioDATs/AudioInfo.cs index 13df8f0..cf67200 100644 --- a/src/NTwain/Triplets/AudioDATs/AudioInfo.cs +++ b/src/NTwain/Triplets/AudioDATs/AudioInfo.cs @@ -1,45 +1,42 @@ using NTwain.Data; using NTwain.DSM; -namespace NTwain.Triplets.AudioDATs -{ - /// - /// Contains calls used with and . - /// - public class AudioInfo - { - public TWRC Get(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, out TW_AUDIOINFO data) - => DoIt(ref app, ref ds, MSG.GET, out data); +namespace NTwain.Triplets.AudioDATs; - static TWRC DoIt(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, MSG msg, out TW_AUDIOINFO data) +/// +/// Contains calls used with and . +/// +public class AudioInfo +{ + public TWRC Get(TWIdentityWrapper app, TWIdentityWrapper ds, out TW_AUDIOINFO data) + => DoIt(app, ds, MSG.GET, out data); + + static TWRC DoIt(TWIdentityWrapper app, TWIdentityWrapper ds, MSG msg, out TW_AUDIOINFO data) { - data = default; - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + data = default; + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.AUDIO, DAT.AUDIOINFO, msg, ref data); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.AUDIO, DAT.AUDIOINFO, msg, ref data); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.AUDIO, DAT.AUDIOINFO, msg, ref data); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.AUDIO, DAT.AUDIOINFO, msg, ref data); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.AUDIO, DAT.AUDIOINFO, msg, ref data); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.AUDIO, DAT.AUDIOINFO, msg, ref data); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.AUDIO, DAT.AUDIOINFO, msg, ref data); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.AUDIO, DAT.AUDIOINFO, msg, ref data); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/AudioDATs/AudioNativeXfer.cs b/src/NTwain/Triplets/AudioDATs/AudioNativeXfer.cs index 514b72f..f5ce12b 100644 --- a/src/NTwain/Triplets/AudioDATs/AudioNativeXfer.cs +++ b/src/NTwain/Triplets/AudioDATs/AudioNativeXfer.cs @@ -2,45 +2,42 @@ using NTwain.DSM; using System; -namespace NTwain.Triplets.AudioDATs -{ - /// - /// Contains calls used with and . - /// - public class AudioNativeXfer - { - public TWRC Get(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, out IntPtr data) - => DoIt(ref app, ref ds, MSG.GET, out data); +namespace NTwain.Triplets.AudioDATs; - static TWRC DoIt(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, MSG msg, out IntPtr data) +/// +/// Contains calls used with and . +/// +public class AudioNativeXfer +{ + public TWRC Get(TWIdentityWrapper app, TWIdentityWrapper ds, out IntPtr data) + => DoIt(app, ds, MSG.GET, out data); + + static TWRC DoIt(TWIdentityWrapper app, TWIdentityWrapper ds, MSG msg, out IntPtr data) { - data = default; - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + data = default; + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.AUDIO, DAT.AUDIONATIVEXFER, msg, ref data); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.AUDIO, DAT.AUDIONATIVEXFER, msg, ref data); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.AUDIO, DAT.AUDIONATIVEXFER, msg, ref data); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.AUDIO, DAT.AUDIONATIVEXFER, msg, ref data); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.AUDIO, DAT.AUDIONATIVEXFER, msg, ref data); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.AUDIO, DAT.AUDIONATIVEXFER, msg, ref data); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.AUDIO, DAT.AUDIONATIVEXFER, msg, ref data); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.AUDIO, DAT.AUDIONATIVEXFER, msg, ref data); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ControlDATs/Callback.cs b/src/NTwain/Triplets/ControlDATs/Callback.cs index a2bed13..ed59df2 100644 --- a/src/NTwain/Triplets/ControlDATs/Callback.cs +++ b/src/NTwain/Triplets/ControlDATs/Callback.cs @@ -1,41 +1,38 @@ using NTwain.Data; using NTwain.DSM; -namespace NTwain.Triplets.ControlDATs +namespace NTwain.Triplets.ControlDATs; + +/// +/// Contains calls used with and . +/// +public class Callback { - /// - /// Contains calls used with and . - /// - public class Callback - { - public TWRC RegisterCallback(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_CALLBACK data) + public TWRC RegisterCallback(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_CALLBACK data) { - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, DAT.CALLBACK, MSG.REGISTER_CALLBACK, ref data); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, DAT.CALLBACK, MSG.REGISTER_CALLBACK, ref data); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, DAT.CALLBACK, MSG.REGISTER_CALLBACK, ref data); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, DAT.CALLBACK, MSG.REGISTER_CALLBACK, ref data); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, DAT.CALLBACK, MSG.REGISTER_CALLBACK, ref data); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, DAT.CALLBACK, MSG.REGISTER_CALLBACK, ref data); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.CONTROL, DAT.CALLBACK, MSG.REGISTER_CALLBACK, ref data); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.CONTROL, DAT.CALLBACK, MSG.REGISTER_CALLBACK, ref data); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ControlDATs/Callback2.cs b/src/NTwain/Triplets/ControlDATs/Callback2.cs index 8df4c24..19bc222 100644 --- a/src/NTwain/Triplets/ControlDATs/Callback2.cs +++ b/src/NTwain/Triplets/ControlDATs/Callback2.cs @@ -1,41 +1,38 @@ using NTwain.Data; using NTwain.DSM; -namespace NTwain.Triplets.ControlDATs +namespace NTwain.Triplets.ControlDATs; + +/// +/// Contains calls used with and . +/// +public class Callback2 { - /// - /// Contains calls used with and . - /// - public class Callback2 - { - public TWRC RegisterCallback(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_CALLBACK2 data) + public TWRC RegisterCallback(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_CALLBACK2 data) { - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, DAT.CALLBACK2, MSG.REGISTER_CALLBACK, ref data); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, DAT.CALLBACK2, MSG.REGISTER_CALLBACK, ref data); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, DAT.CALLBACK2, MSG.REGISTER_CALLBACK, ref data); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, DAT.CALLBACK2, MSG.REGISTER_CALLBACK, ref data); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, DAT.CALLBACK2, MSG.REGISTER_CALLBACK, ref data); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, DAT.CALLBACK2, MSG.REGISTER_CALLBACK, ref data); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.CONTROL, DAT.CALLBACK2, MSG.REGISTER_CALLBACK, ref data); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.CONTROL, DAT.CALLBACK2, MSG.REGISTER_CALLBACK, ref data); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ControlDATs/Capability.cs b/src/NTwain/Triplets/ControlDATs/Capability.cs index f4fe906..b758bed 100644 --- a/src/NTwain/Triplets/ControlDATs/Capability.cs +++ b/src/NTwain/Triplets/ControlDATs/Capability.cs @@ -1,64 +1,61 @@ using NTwain.Data; using NTwain.DSM; -namespace NTwain.Triplets.ControlDATs -{ - /// - /// Contains calls used with and . - /// - public class Capability - { - public TWRC Get(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_CAPABILITY data) - => DoIt(ref app, ref ds, MSG.GET, ref data); - public TWRC GetCurrent(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_CAPABILITY data) - => DoIt(ref app, ref ds, MSG.GETCURRENT, ref data); - public TWRC GetDefault(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_CAPABILITY data) - => DoIt(ref app, ref ds, MSG.GETDEFAULT, ref data); - public TWRC GetHelp(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_CAPABILITY data) - => DoIt(ref app, ref ds, MSG.GETHELP, ref data); - public TWRC GetLabel(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_CAPABILITY data) - => DoIt(ref app, ref ds, MSG.GETLABEL, ref data); - public TWRC GetLabelEnum(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_CAPABILITY data) - => DoIt(ref app, ref ds, MSG.GETLABELENUM, ref data); - public TWRC QuerySupport(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_CAPABILITY data) - => DoIt(ref app, ref ds, MSG.QUERYSUPPORT, ref data); - public TWRC Reset(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_CAPABILITY data) - => DoIt(ref app, ref ds, MSG.RESET, ref data); - public TWRC ResetAll(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_CAPABILITY data) - => DoIt(ref app, ref ds, MSG.RESETALL, ref data); - public TWRC Set(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_CAPABILITY data) - => DoIt(ref app, ref ds, MSG.SET, ref data); - public TWRC SetConstraint(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_CAPABILITY data) - => DoIt(ref app, ref ds, MSG.SETCONSTRAINT, ref data); +namespace NTwain.Triplets.ControlDATs; - static TWRC DoIt(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, MSG msg, ref TW_CAPABILITY data) +/// +/// Contains calls used with and . +/// +public class Capability +{ + public TWRC Get(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_CAPABILITY data) + => DoIt(app, ds, MSG.GET, ref data); + public TWRC GetCurrent(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_CAPABILITY data) + => DoIt(app, ds, MSG.GETCURRENT, ref data); + public TWRC GetDefault(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_CAPABILITY data) + => DoIt(app, ds, MSG.GETDEFAULT, ref data); + public TWRC GetHelp(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_CAPABILITY data) + => DoIt(app, ds, MSG.GETHELP, ref data); + public TWRC GetLabel(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_CAPABILITY data) + => DoIt(app, ds, MSG.GETLABEL, ref data); + public TWRC GetLabelEnum(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_CAPABILITY data) + => DoIt(app, ds, MSG.GETLABELENUM, ref data); + public TWRC QuerySupport(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_CAPABILITY data) + => DoIt(app, ds, MSG.QUERYSUPPORT, ref data); + public TWRC Reset(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_CAPABILITY data) + => DoIt(app, ds, MSG.RESET, ref data); + public TWRC ResetAll(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_CAPABILITY data) + => DoIt(app, ds, MSG.RESETALL, ref data); + public TWRC Set(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_CAPABILITY data) + => DoIt(app, ds, MSG.SET, ref data); + public TWRC SetConstraint(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_CAPABILITY data) + => DoIt(app, ds, MSG.SETCONSTRAINT, ref data); + + static TWRC DoIt(TWIdentityWrapper app, TWIdentityWrapper ds, MSG msg, ref TW_CAPABILITY data) { - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, DAT.CAPABILITY, msg, ref data); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, DAT.CAPABILITY, msg, ref data); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, DAT.CAPABILITY, msg, ref data); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, DAT.CAPABILITY, msg, ref data); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, DAT.CAPABILITY, msg, ref data); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, DAT.CAPABILITY, msg, ref data); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.CONTROL, DAT.CAPABILITY, msg, ref data); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.CONTROL, DAT.CAPABILITY, msg, ref data); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ControlDATs/CapabilityCustom.cs b/src/NTwain/Triplets/ControlDATs/CapabilityCustom.cs index e5b92ff..6a8422a 100644 --- a/src/NTwain/Triplets/ControlDATs/CapabilityCustom.cs +++ b/src/NTwain/Triplets/ControlDATs/CapabilityCustom.cs @@ -1,62 +1,59 @@ using NTwain.Data; using NTwain.DSM; -namespace NTwain.Triplets.ControlDATs -{ - /// - /// Contains calls used with and custom capability DAT for certain devices. - /// - public class CapabilityCustom - { - public TWRC Get(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ushort customDAT, ref TW_CAPABILITY data) - => DoIt(ref app, ref ds, customDAT, MSG.GET, ref data); - public TWRC GetCurrent(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ushort customDAT, ref TW_CAPABILITY data) - => DoIt(ref app, ref ds, customDAT, MSG.GETCURRENT, ref data); - public TWRC GetDefault(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ushort customDAT, ref TW_CAPABILITY data) - => DoIt(ref app, ref ds, customDAT, MSG.GETDEFAULT, ref data); - public TWRC GetHelp(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ushort customDAT, ref TW_CAPABILITY data) - => DoIt(ref app, ref ds, customDAT, MSG.GETHELP, ref data); - public TWRC GetLabel(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ushort customDAT, ref TW_CAPABILITY data) - => DoIt(ref app, ref ds, customDAT, MSG.GETLABEL, ref data); - public TWRC GetLabelEnum(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ushort customDAT, ref TW_CAPABILITY data) - => DoIt(ref app, ref ds, customDAT, MSG.GETLABELENUM, ref data); - public TWRC QuerySupport(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ushort customDAT, ref TW_CAPABILITY data) - => DoIt(ref app, ref ds, customDAT, MSG.QUERYSUPPORT, ref data); - public TWRC Reset(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ushort customDAT, ref TW_CAPABILITY data) - => DoIt(ref app, ref ds, customDAT, MSG.RESET, ref data); - public TWRC ResetAll(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ushort customDAT, ref TW_CAPABILITY data) - => DoIt(ref app, ref ds, customDAT, MSG.RESETALL, ref data); - public TWRC Set(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ushort customDAT, ref TW_CAPABILITY data) - => DoIt(ref app, ref ds, customDAT, MSG.SET, ref data); +namespace NTwain.Triplets.ControlDATs; - static TWRC DoIt(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ushort dat, MSG msg, ref TW_CAPABILITY data) +/// +/// Contains calls used with and custom capability DAT for certain devices. +/// +public class CapabilityCustom +{ + public TWRC Get(TWIdentityWrapper app, TWIdentityWrapper ds, ushort customDAT, ref TW_CAPABILITY data) + => DoIt(app, ds, customDAT, MSG.GET, ref data); + public TWRC GetCurrent(TWIdentityWrapper app, TWIdentityWrapper ds, ushort customDAT, ref TW_CAPABILITY data) + => DoIt(app, ds, customDAT, MSG.GETCURRENT, ref data); + public TWRC GetDefault(TWIdentityWrapper app, TWIdentityWrapper ds, ushort customDAT, ref TW_CAPABILITY data) + => DoIt(app, ds, customDAT, MSG.GETDEFAULT, ref data); + public TWRC GetHelp(TWIdentityWrapper app, TWIdentityWrapper ds, ushort customDAT, ref TW_CAPABILITY data) + => DoIt(app, ds, customDAT, MSG.GETHELP, ref data); + public TWRC GetLabel(TWIdentityWrapper app, TWIdentityWrapper ds, ushort customDAT, ref TW_CAPABILITY data) + => DoIt(app, ds, customDAT, MSG.GETLABEL, ref data); + public TWRC GetLabelEnum(TWIdentityWrapper app, TWIdentityWrapper ds, ushort customDAT, ref TW_CAPABILITY data) + => DoIt(app, ds, customDAT, MSG.GETLABELENUM, ref data); + public TWRC QuerySupport(TWIdentityWrapper app, TWIdentityWrapper ds, ushort customDAT, ref TW_CAPABILITY data) + => DoIt(app, ds, customDAT, MSG.QUERYSUPPORT, ref data); + public TWRC Reset(TWIdentityWrapper app, TWIdentityWrapper ds, ushort customDAT, ref TW_CAPABILITY data) + => DoIt(app, ds, customDAT, MSG.RESET, ref data); + public TWRC ResetAll(TWIdentityWrapper app, TWIdentityWrapper ds, ushort customDAT, ref TW_CAPABILITY data) + => DoIt(app, ds, customDAT, MSG.RESETALL, ref data); + public TWRC Set(TWIdentityWrapper app, TWIdentityWrapper ds, ushort customDAT, ref TW_CAPABILITY data) + => DoIt(app, ds, customDAT, MSG.SET, ref data); + + static TWRC DoIt(TWIdentityWrapper app, TWIdentityWrapper ds, ushort dat, MSG msg, ref TW_CAPABILITY data) { - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, (DAT)dat, msg, ref data); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, (DAT)dat, msg, ref data); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, (DAT)dat, msg, ref data); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, (DAT)dat, msg, ref data); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, (DAT)dat, msg, ref data); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, (DAT)dat, msg, ref data); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.CONTROL, (DAT)dat, msg, ref data); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.CONTROL, (DAT)dat, msg, ref data); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ControlDATs/CustomDsData.cs b/src/NTwain/Triplets/ControlDATs/CustomDsData.cs index 86ffc13..b52d3a1 100644 --- a/src/NTwain/Triplets/ControlDATs/CustomDsData.cs +++ b/src/NTwain/Triplets/ControlDATs/CustomDsData.cs @@ -1,50 +1,47 @@ using NTwain.Data; using NTwain.DSM; -namespace NTwain.Triplets.ControlDATs +namespace NTwain.Triplets.ControlDATs; + +/// +/// Contains calls used with and . +/// +public class CustomDsData { - /// - /// Contains calls used with and . - /// - public class CustomDsData - { - public TWRC Get(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, out TW_CUSTOMDSDATA data) + public TWRC Get(TWIdentityWrapper app, TWIdentityWrapper ds, out TW_CUSTOMDSDATA data) { - data = default; - return DoIt(ref app, ref ds, MSG.GET, ref data); + data = default; + return DoIt(app, ds, MSG.GET, ref data); } - public TWRC Set(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_CUSTOMDSDATA data) - => DoIt(ref app, ref ds, MSG.SET, ref data); + public TWRC Set(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_CUSTOMDSDATA data) + => DoIt(app, ds, MSG.SET, ref data); - static TWRC DoIt(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, MSG msg, ref TW_CUSTOMDSDATA data) + static TWRC DoIt(TWIdentityWrapper app, TWIdentityWrapper ds, MSG msg, ref TW_CUSTOMDSDATA data) { - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, DAT.CUSTOMDSDATA, msg, ref data); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, DAT.CUSTOMDSDATA, msg, ref data); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, DAT.CUSTOMDSDATA, msg, ref data); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, DAT.CUSTOMDSDATA, msg, ref data); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, DAT.CUSTOMDSDATA, msg, ref data); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, DAT.CUSTOMDSDATA, msg, ref data); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.CONTROL, DAT.CUSTOMDSDATA, msg, ref data); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.CONTROL, DAT.CUSTOMDSDATA, msg, ref data); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ControlDATs/DeviceEvent.cs b/src/NTwain/Triplets/ControlDATs/DeviceEvent.cs index 38f120d..3fe28d5 100644 --- a/src/NTwain/Triplets/ControlDATs/DeviceEvent.cs +++ b/src/NTwain/Triplets/ControlDATs/DeviceEvent.cs @@ -1,42 +1,39 @@ using NTwain.Data; using NTwain.DSM; -namespace NTwain.Triplets.ControlDATs +namespace NTwain.Triplets.ControlDATs; + +/// +/// Contains calls used with and . +/// +public class DeviceEvent { - /// - /// Contains calls used with and . - /// - public class DeviceEvent - { - public TWRC Get(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, out TW_DEVICEEVENT data) + public TWRC Get(TWIdentityWrapper app, TWIdentityWrapper ds, out TW_DEVICEEVENT data) { - data = default; - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + data = default; + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, DAT.DEVICEEVENT, MSG.GET, ref data); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, DAT.DEVICEEVENT, MSG.GET, ref data); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, DAT.DEVICEEVENT, MSG.GET, ref data); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, DAT.DEVICEEVENT, MSG.GET, ref data); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, DAT.DEVICEEVENT, MSG.GET, ref data); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, DAT.DEVICEEVENT, MSG.GET, ref data); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.CONTROL, DAT.DEVICEEVENT, MSG.GET, ref data); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.CONTROL, DAT.DEVICEEVENT, MSG.GET, ref data); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ControlDATs/EntryPoint.cs b/src/NTwain/Triplets/ControlDATs/EntryPoint.cs index 03f61b3..3a3938e 100644 --- a/src/NTwain/Triplets/ControlDATs/EntryPoint.cs +++ b/src/NTwain/Triplets/ControlDATs/EntryPoint.cs @@ -3,76 +3,74 @@ using NTwain.DSM; using System; using System.Runtime.InteropServices; -namespace NTwain.Triplets.ControlDATs +namespace NTwain.Triplets.ControlDATs; + +/// +/// Contains calls used with and . +/// +public class EntryPoint { - /// - /// Contains calls used with and . - /// - public class EntryPoint - { - public TWRC Get(ref TW_IDENTITY_LEGACY app, out TW_ENTRYPOINT_DELEGATES entry) + public TWRC Get(TWIdentityWrapper app, out TW_ENTRYPOINT_DELEGATES entry) { - entry = default; - TW_ENTRYPOINT rawentry = new() - { - Size = (uint)Marshal.SizeOf() - }; - var rc = DoIt(ref app, MSG.GET, ref rawentry); - if (rc == TWRC.SUCCESS) - { - entry.Size = rawentry.Size; - entry.DSM_Entry = rawentry.DSM_Entry; - if (rawentry.DSM_MemAllocate != IntPtr.Zero) + entry = default; + TW_ENTRYPOINT rawentry = new() { - entry.DSM_MemAllocate = (DSM_MEMALLOC)Marshal.GetDelegateForFunctionPointer(rawentry.DSM_MemAllocate, typeof(DSM_MEMALLOC)); - } - if (rawentry.DSM_MemFree != IntPtr.Zero) + Size = (uint)Marshal.SizeOf() + }; + var rc = DoIt(app, MSG.GET, ref rawentry); + if (rc == TWRC.SUCCESS) { - entry.DSM_MemFree = (DSM_MEMFREE)Marshal.GetDelegateForFunctionPointer(rawentry.DSM_MemFree, typeof(DSM_MEMFREE)); + entry.Size = rawentry.Size; + entry.DSM_Entry = rawentry.DSM_Entry; + if (rawentry.DSM_MemAllocate != IntPtr.Zero) + { + entry.DSM_MemAllocate = (DSM_MEMALLOC)Marshal.GetDelegateForFunctionPointer(rawentry.DSM_MemAllocate, typeof(DSM_MEMALLOC)); + } + if (rawentry.DSM_MemFree != IntPtr.Zero) + { + entry.DSM_MemFree = (DSM_MEMFREE)Marshal.GetDelegateForFunctionPointer(rawentry.DSM_MemFree, typeof(DSM_MEMFREE)); + } + if (rawentry.DSM_MemLock != IntPtr.Zero) + { + entry.DSM_MemLock = (DSM_MEMLOCK)Marshal.GetDelegateForFunctionPointer(rawentry.DSM_MemLock, typeof(DSM_MEMLOCK)); + } + if (rawentry.DSM_MemUnlock != IntPtr.Zero) + { + entry.DSM_MemUnlock = (DSM_MEMUNLOCK)Marshal.GetDelegateForFunctionPointer(rawentry.DSM_MemUnlock, typeof(DSM_MEMUNLOCK)); + } } - if (rawentry.DSM_MemLock != IntPtr.Zero) - { - entry.DSM_MemLock = (DSM_MEMLOCK)Marshal.GetDelegateForFunctionPointer(rawentry.DSM_MemLock, typeof(DSM_MEMLOCK)); - } - if (rawentry.DSM_MemUnlock != IntPtr.Zero) - { - entry.DSM_MemUnlock = (DSM_MEMUNLOCK)Marshal.GetDelegateForFunctionPointer(rawentry.DSM_MemUnlock, typeof(DSM_MEMUNLOCK)); - } - } - return rc; + return rc; } - static TWRC DoIt(ref TW_IDENTITY_LEGACY app, MSG msg, ref TW_ENTRYPOINT entry) + static TWRC DoIt(TWIdentityWrapper app, MSG msg, ref TW_ENTRYPOINT entry) { - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, IntPtr.Zero, DG.CONTROL, DAT.ENTRYPOINT, msg, ref entry); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, IntPtr.Zero, DG.CONTROL, DAT.ENTRYPOINT, msg, ref entry); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, IntPtr.Zero, DG.CONTROL, DAT.ENTRYPOINT, msg, ref entry); + } } - else + //else if (TwainPlatform.IsLinux) + //{ + // var app = Session._appIdentity; + //} + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, IntPtr.Zero, DG.CONTROL, DAT.ENTRYPOINT, msg, ref entry); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, IntPtr.Zero, DG.CONTROL, DAT.ENTRYPOINT, msg, ref entry); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, IntPtr.Zero, DG.CONTROL, DAT.ENTRYPOINT, msg, ref entry); + } } - } - //else if (TwainPlatform.IsLinux) - //{ - // var app = Session._appIdentity; - //} - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, IntPtr.Zero, DG.CONTROL, DAT.ENTRYPOINT, msg, ref entry); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, IntPtr.Zero, DG.CONTROL, DAT.ENTRYPOINT, msg, ref entry); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ControlDATs/Event.cs b/src/NTwain/Triplets/ControlDATs/Event.cs index e8a19e2..58e7758 100644 --- a/src/NTwain/Triplets/ControlDATs/Event.cs +++ b/src/NTwain/Triplets/ControlDATs/Event.cs @@ -1,41 +1,38 @@ using NTwain.Data; using NTwain.DSM; -namespace NTwain.Triplets.ControlDATs +namespace NTwain.Triplets.ControlDATs; + +/// +/// Contains calls used with and . +/// +public class Event { - /// - /// Contains calls used with and . - /// - public class Event - { - public TWRC ProcessEvent(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_EVENT data) + public TWRC ProcessEvent(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_EVENT data) { - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, DAT.EVENT, MSG.PROCESSEVENT, ref data); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, DAT.EVENT, MSG.PROCESSEVENT, ref data); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, DAT.EVENT, MSG.PROCESSEVENT, ref data); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, DAT.EVENT, MSG.PROCESSEVENT, ref data); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, DAT.EVENT, MSG.PROCESSEVENT, ref data); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, DAT.EVENT, MSG.PROCESSEVENT, ref data); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.CONTROL, DAT.EVENT, MSG.PROCESSEVENT, ref data); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.CONTROL, DAT.EVENT, MSG.PROCESSEVENT, ref data); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ControlDATs/FileSystem.cs b/src/NTwain/Triplets/ControlDATs/FileSystem.cs index bd6b49d..4971077 100644 --- a/src/NTwain/Triplets/ControlDATs/FileSystem.cs +++ b/src/NTwain/Triplets/ControlDATs/FileSystem.cs @@ -1,64 +1,61 @@ using NTwain.Data; using NTwain.DSM; -namespace NTwain.Triplets.ControlDATs -{ - /// - /// Contains calls used with and . - /// - public class FileSystem - { - public TWRC AutomaticCaptureDirectory(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_FILESYSTEM data) - => DoIt(ref app, ref ds, MSG.AUTOMATICCAPTUREDIRECTORY, ref data); - public TWRC ChangeDirectory(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_FILESYSTEM data) - => DoIt(ref app, ref ds, MSG.CHANGEDIRECTORY, ref data); - public TWRC Copy(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_FILESYSTEM data) - => DoIt(ref app, ref ds, MSG.COPY, ref data); - public TWRC CreateDirectory(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_FILESYSTEM data) - => DoIt(ref app, ref ds, MSG.CREATEDIRECTORY, ref data); - public TWRC Delete(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_FILESYSTEM data) - => DoIt(ref app, ref ds, MSG.DELETE, ref data); - public TWRC FormatMedia(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_FILESYSTEM data) - => DoIt(ref app, ref ds, MSG.FORMATMEDIA, ref data); - public TWRC GetClose(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_FILESYSTEM data) - => DoIt(ref app, ref ds, MSG.GETCLOSE, ref data); - public TWRC GetFirstFile(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_FILESYSTEM data) - => DoIt(ref app, ref ds, MSG.GETFIRSTFILE, ref data); - public TWRC GetInfo(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_FILESYSTEM data) - => DoIt(ref app, ref ds, MSG.GETINFO, ref data); - public TWRC GetNextFile(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_FILESYSTEM data) - => DoIt(ref app, ref ds, MSG.GETNEXTFILE, ref data); - public TWRC Rename(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_FILESYSTEM data) - => DoIt(ref app, ref ds, MSG.RENAME, ref data); +namespace NTwain.Triplets.ControlDATs; - static TWRC DoIt(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, MSG msg, ref TW_FILESYSTEM data) +/// +/// Contains calls used with and . +/// +public class FileSystem +{ + public TWRC AutomaticCaptureDirectory(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_FILESYSTEM data) + => DoIt(app, ds, MSG.AUTOMATICCAPTUREDIRECTORY, ref data); + public TWRC ChangeDirectory(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_FILESYSTEM data) + => DoIt(app, ds, MSG.CHANGEDIRECTORY, ref data); + public TWRC Copy(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_FILESYSTEM data) + => DoIt(app, ds, MSG.COPY, ref data); + public TWRC CreateDirectory(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_FILESYSTEM data) + => DoIt(app, ds, MSG.CREATEDIRECTORY, ref data); + public TWRC Delete(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_FILESYSTEM data) + => DoIt(app, ds, MSG.DELETE, ref data); + public TWRC FormatMedia(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_FILESYSTEM data) + => DoIt(app, ds, MSG.FORMATMEDIA, ref data); + public TWRC GetClose(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_FILESYSTEM data) + => DoIt(app, ds, MSG.GETCLOSE, ref data); + public TWRC GetFirstFile(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_FILESYSTEM data) + => DoIt(app, ds, MSG.GETFIRSTFILE, ref data); + public TWRC GetInfo(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_FILESYSTEM data) + => DoIt(app, ds, MSG.GETINFO, ref data); + public TWRC GetNextFile(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_FILESYSTEM data) + => DoIt(app, ds, MSG.GETNEXTFILE, ref data); + public TWRC Rename(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_FILESYSTEM data) + => DoIt(app, ds, MSG.RENAME, ref data); + + static TWRC DoIt(TWIdentityWrapper app, TWIdentityWrapper ds, MSG msg, ref TW_FILESYSTEM data) { - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, DAT.FILESYSTEM, msg, ref data); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, DAT.FILESYSTEM, msg, ref data); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, DAT.FILESYSTEM, msg, ref data); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, DAT.FILESYSTEM, msg, ref data); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, DAT.FILESYSTEM, msg, ref data); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, DAT.FILESYSTEM, msg, ref data); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.CONTROL, DAT.FILESYSTEM, msg, ref data); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.CONTROL, DAT.FILESYSTEM, msg, ref data); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ControlDATs/Identity.cs b/src/NTwain/Triplets/ControlDATs/Identity.cs index b157e9d..5a51ac1 100644 --- a/src/NTwain/Triplets/ControlDATs/Identity.cs +++ b/src/NTwain/Triplets/ControlDATs/Identity.cs @@ -2,18 +2,18 @@ using NTwain.DSM; using System; -namespace NTwain.Triplets.ControlDATs -{ - /// - /// Contains calls used with and . - /// - public class Identity - { - public TWRC OpenDS(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds) - => DoIt(ref app, MSG.OPENDS, ref ds); +namespace NTwain.Triplets.ControlDATs; - public TWRC CloseDS(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds) - => DoIt(ref app, MSG.CLOSEDS, ref ds); +/// +/// Contains calls used with and . +/// +public class Identity +{ + public TWRC OpenDS(TWIdentityWrapper app, TWIdentityWrapper ds) + => DoIt(app, MSG.OPENDS, ds); + + public TWRC CloseDS(TWIdentityWrapper app, TWIdentityWrapper ds) + => DoIt(app, MSG.CLOSEDS, ds); /// /// Opens the TWAIN data source selector dialog @@ -22,16 +22,16 @@ namespace NTwain.Triplets.ControlDATs /// /// /// - public TWRC UserSelect(ref TW_IDENTITY_LEGACY app, out TW_IDENTITY_LEGACY ds) + public TWRC UserSelect(TWIdentityWrapper app, out TWIdentityWrapper ds) { - ds = default; - return DoIt(ref app, MSG.USERSELECT, ref ds); + ds = new(); + return DoIt(app, MSG.USERSELECT, ds); } - public TWRC GetDefault(ref TW_IDENTITY_LEGACY app, out TW_IDENTITY_LEGACY ds) + public TWRC GetDefault(TWIdentityWrapper app, out TWIdentityWrapper ds) { - ds = default; - return DoIt(ref app, MSG.GETDEFAULT, ref ds); + ds = new(); + return DoIt(app, MSG.GETDEFAULT, ds); } /// @@ -40,8 +40,8 @@ namespace NTwain.Triplets.ControlDATs /// /// /// - public TWRC Set(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds) - => DoIt(ref app, MSG.SET, ref ds); + public TWRC Set(TWIdentityWrapper app, TWIdentityWrapper ds) + => DoIt(app, MSG.SET, ds); /// /// Gets the first available data source in an enumerating fashion @@ -50,10 +50,10 @@ namespace NTwain.Triplets.ControlDATs /// /// /// - public TWRC GetFirst(ref TW_IDENTITY_LEGACY app, out TW_IDENTITY_LEGACY ds) + public TWRC GetFirst(TWIdentityWrapper app, out TWIdentityWrapper ds) { - ds = default; - return DoIt(ref app, MSG.GETFIRST, ref ds); + ds = new(); + return DoIt(app, MSG.GETFIRST, ds); } /// @@ -63,42 +63,40 @@ namespace NTwain.Triplets.ControlDATs /// /// /// - public TWRC GetNext(ref TW_IDENTITY_LEGACY app, out TW_IDENTITY_LEGACY ds) + public TWRC GetNext(TWIdentityWrapper app, out TWIdentityWrapper ds) { - ds = default; - return DoIt(ref app, MSG.GETNEXT, ref ds); + ds = new(); + return DoIt(app, MSG.GETNEXT, ds); } - static TWRC DoIt(ref TW_IDENTITY_LEGACY app, MSG msg, ref TW_IDENTITY_LEGACY ds) + static TWRC DoIt(TWIdentityWrapper app, MSG msg, TWIdentityWrapper ds) { - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, IntPtr.Zero, DG.CONTROL, DAT.IDENTITY, msg, ref ds); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, IntPtr.Zero, DG.CONTROL, DAT.IDENTITY, msg, ref ds.TW_IDENTITY_LEGACY); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, IntPtr.Zero, DG.CONTROL, DAT.IDENTITY, msg, ref ds.TW_IDENTITY_LEGACY); + } + ds.SetIdentity(ds.TW_IDENTITY_LEGACY); } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, IntPtr.Zero, DG.CONTROL, DAT.IDENTITY, msg, ref ds); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, IntPtr.Zero, DG.CONTROL, DAT.IDENTITY, msg, ref ds.TW_IDENTITY_MACOSX); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, IntPtr.Zero, DG.CONTROL, DAT.IDENTITY, msg, ref ds.TW_IDENTITY_MACOSX); + } + ds.SetIdentity(ds.TW_IDENTITY_MACOSX); } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX osxds = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, IntPtr.Zero, DG.CONTROL, DAT.IDENTITY, msg, ref osxds); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, IntPtr.Zero, DG.CONTROL, DAT.IDENTITY, msg, ref osxds); - } - ds = osxds; - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ControlDATs/Metrics.cs b/src/NTwain/Triplets/ControlDATs/Metrics.cs index 5d559b2..8f659dd 100644 --- a/src/NTwain/Triplets/ControlDATs/Metrics.cs +++ b/src/NTwain/Triplets/ControlDATs/Metrics.cs @@ -2,44 +2,41 @@ using NTwain.DSM; using System.Runtime.InteropServices; -namespace NTwain.Triplets.ControlDATs -{ - /// - /// Contains calls used with and . - /// - public class Metrics - { - public TWRC Get(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, out TW_METRICS data) - { - data = default; - data.SizeOf = (uint)Marshal.SizeOf(); +namespace NTwain.Triplets.ControlDATs; - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) +/// +/// Contains calls used with and . +/// +public class Metrics +{ + public TWRC Get(TWIdentityWrapper app, TWIdentityWrapper ds, out TW_METRICS data) + { + data = default; + data.SizeOf = (uint)Marshal.SizeOf(); + + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, DAT.METRICS, MSG.GET, ref data); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, DAT.METRICS, MSG.GET, ref data); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, DAT.METRICS, MSG.GET, ref data); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, DAT.METRICS, MSG.GET, ref data); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, DAT.METRICS, MSG.GET, ref data); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, DAT.METRICS, MSG.GET, ref data); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.CONTROL, DAT.METRICS, MSG.GET, ref data); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.CONTROL, DAT.METRICS, MSG.GET, ref data); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ControlDATs/Parent.cs b/src/NTwain/Triplets/ControlDATs/Parent.cs index d5519f5..c52ac71 100644 --- a/src/NTwain/Triplets/ControlDATs/Parent.cs +++ b/src/NTwain/Triplets/ControlDATs/Parent.cs @@ -2,21 +2,21 @@ using NTwain.DSM; using System; -namespace NTwain.Triplets.ControlDATs +namespace NTwain.Triplets.ControlDATs; + +/// +/// Contains calls used with and . +/// +public class Parent { - /// - /// Contains calls used with and . - /// - public class Parent - { /// /// Loads and opens the DSM. /// /// /// Required if on Windows. /// - public TWRC OpenDSM(ref TW_IDENTITY_LEGACY app, IntPtr hwnd) - => DoIt(ref app, MSG.OPENDSM, hwnd); + public TWRC OpenDSM(TWIdentityWrapper app, IntPtr hwnd) + => DoIt(app, MSG.OPENDSM, hwnd); /// /// Closes the DSM. @@ -24,42 +24,40 @@ namespace NTwain.Triplets.ControlDATs /// /// Required if on Windows. /// - public TWRC CloseDSM(ref TW_IDENTITY_LEGACY app, IntPtr hwnd) - => DoIt(ref app, MSG.CLOSEDSM, hwnd); + public TWRC CloseDSM(TWIdentityWrapper app, IntPtr hwnd) + => DoIt(app, MSG.CLOSEDSM, hwnd); - static TWRC DoIt(ref TW_IDENTITY_LEGACY app, MSG msg, IntPtr hwnd) + static TWRC DoIt(TWIdentityWrapper app, MSG msg, IntPtr hwnd) { - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, IntPtr.Zero, DG.CONTROL, DAT.PARENT, msg, ref hwnd); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, IntPtr.Zero, DG.CONTROL, DAT.PARENT, msg, ref hwnd); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, IntPtr.Zero, DG.CONTROL, DAT.PARENT, msg, ref hwnd); + } } - else + //else if (TwainPlatform.IsLinux) + //{ + // var app = Session._appIdentity; + // rc = NativeMethods.LinuxDsmEntryParent(ref app, IntPtr.Zero, DG.CONTROL, DAT.PARENT, msg, ref hwnd); + // if (rc == TWRC.SUCCESS) Session._appIdentity = app; + //} + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, IntPtr.Zero, DG.CONTROL, DAT.PARENT, msg, ref hwnd); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, IntPtr.Zero, DG.CONTROL, DAT.PARENT, msg, hwnd); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, IntPtr.Zero, DG.CONTROL, DAT.PARENT, msg, hwnd); + } } - } - //else if (TwainPlatform.IsLinux) - //{ - // var app = Session._appIdentity; - // rc = NativeMethods.LinuxDsmEntryParent(ref app, IntPtr.Zero, DG.CONTROL, DAT.PARENT, msg, ref hwnd); - // if (rc == TWRC.SUCCESS) Session._appIdentity = app; - //} - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, IntPtr.Zero, DG.CONTROL, DAT.PARENT, msg, hwnd); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, IntPtr.Zero, DG.CONTROL, DAT.PARENT, msg, hwnd); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ControlDATs/Passthru.cs b/src/NTwain/Triplets/ControlDATs/Passthru.cs index 8fa43f8..2fa944a 100644 --- a/src/NTwain/Triplets/ControlDATs/Passthru.cs +++ b/src/NTwain/Triplets/ControlDATs/Passthru.cs @@ -1,41 +1,38 @@ using NTwain.Data; using NTwain.DSM; -namespace NTwain.Triplets.ControlDATs +namespace NTwain.Triplets.ControlDATs; + +/// +/// Contains calls used with and . +/// +public class Passthru { - /// - /// Contains calls used with and . - /// - public class Passthru - { - public TWRC PassThrough(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_PASSTHRU data) + public TWRC PassThrough(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_PASSTHRU data) { - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, DAT.PASSTHRU, MSG.PASSTHRU, ref data); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, DAT.PASSTHRU, MSG.PASSTHRU, ref data); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, DAT.PASSTHRU, MSG.PASSTHRU, ref data); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, DAT.PASSTHRU, MSG.PASSTHRU, ref data); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, DAT.PASSTHRU, MSG.PASSTHRU, ref data); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, DAT.PASSTHRU, MSG.PASSTHRU, ref data); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.CONTROL, DAT.PASSTHRU, MSG.PASSTHRU, ref data); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.CONTROL, DAT.PASSTHRU, MSG.PASSTHRU, ref data); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ControlDATs/PendingXfers.cs b/src/NTwain/Triplets/ControlDATs/PendingXfers.cs index 4f6e977..5e18888 100644 --- a/src/NTwain/Triplets/ControlDATs/PendingXfers.cs +++ b/src/NTwain/Triplets/ControlDATs/PendingXfers.cs @@ -1,51 +1,48 @@ using NTwain.Data; using NTwain.DSM; -namespace NTwain.Triplets.ControlDATs +namespace NTwain.Triplets.ControlDATs; + +/// +/// Contains calls used with and . +/// +public class PendingXfers { - /// - /// Contains calls used with and . - /// - public class PendingXfers - { - public TWRC EndXfer(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_PENDINGXFERS data) - => DoIt(ref app, ref ds, MSG.ENDXFER, ref data); - public TWRC Get(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_PENDINGXFERS data) - => DoIt(ref app, ref ds, MSG.GET, ref data); - public TWRC Reset(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_PENDINGXFERS data) - => DoIt(ref app, ref ds, MSG.RESET, ref data); - public TWRC StopFeeder(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_PENDINGXFERS data) - => DoIt(ref app, ref ds, MSG.STOPFEEDER, ref data); + public TWRC EndXfer(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_PENDINGXFERS data) + => DoIt(app, ds, MSG.ENDXFER, ref data); + public TWRC Get(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_PENDINGXFERS data) + => DoIt(app, ds, MSG.GET, ref data); + public TWRC Reset(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_PENDINGXFERS data) + => DoIt(app, ds, MSG.RESET, ref data); + public TWRC StopFeeder(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_PENDINGXFERS data) + => DoIt(app, ds, MSG.STOPFEEDER, ref data); - static TWRC DoIt(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, MSG msg, ref TW_PENDINGXFERS data) + static TWRC DoIt(TWIdentityWrapper app, TWIdentityWrapper ds, MSG msg, ref TW_PENDINGXFERS data) { - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, DAT.PENDINGXFERS, msg, ref data); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, DAT.PENDINGXFERS, msg, ref data); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, DAT.PENDINGXFERS, msg, ref data); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, DAT.PENDINGXFERS, msg, ref data); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, DAT.PENDINGXFERS, msg, ref data); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, DAT.PENDINGXFERS, msg, ref data); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.CONTROL, DAT.PENDINGXFERS, msg, ref data); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.CONTROL, DAT.PENDINGXFERS, msg, ref data); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ControlDATs/SetupFileXfer.cs b/src/NTwain/Triplets/ControlDATs/SetupFileXfer.cs index b2db885..7686425 100644 --- a/src/NTwain/Triplets/ControlDATs/SetupFileXfer.cs +++ b/src/NTwain/Triplets/ControlDATs/SetupFileXfer.cs @@ -1,60 +1,57 @@ using NTwain.Data; using NTwain.DSM; -namespace NTwain.Triplets.ControlDATs +namespace NTwain.Triplets.ControlDATs; + +/// +/// Contains calls used with and . +/// +public class SetupFileXfer { - /// - /// Contains calls used with and . - /// - public class SetupFileXfer - { - public TWRC Get(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, out TW_SETUPFILEXFER data) + public TWRC Get(TWIdentityWrapper app, TWIdentityWrapper ds, out TW_SETUPFILEXFER data) { - data = default; - return DoIt(ref app, ref ds, MSG.GET, ref data); + data = default; + return DoIt(app, ds, MSG.GET, ref data); } - public TWRC Set(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_SETUPFILEXFER data) - => DoIt(ref app, ref ds, MSG.SET, ref data); - public TWRC GetDefault(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, out TW_SETUPFILEXFER data) + public TWRC Set(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_SETUPFILEXFER data) + => DoIt(app, ds, MSG.SET, ref data); + public TWRC GetDefault(TWIdentityWrapper app, TWIdentityWrapper ds, out TW_SETUPFILEXFER data) { - data = default; - return DoIt(ref app, ref ds, MSG.GETDEFAULT, ref data); + data = default; + return DoIt(app, ds, MSG.GETDEFAULT, ref data); } - public TWRC Reset(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, out TW_SETUPFILEXFER data) + public TWRC Reset(TWIdentityWrapper app, TWIdentityWrapper ds, out TW_SETUPFILEXFER data) { - data = default; - return DoIt(ref app, ref ds, MSG.RESET, ref data); + data = default; + return DoIt(app, ds, MSG.RESET, ref data); } - static TWRC DoIt(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, MSG msg, ref TW_SETUPFILEXFER data) + static TWRC DoIt(TWIdentityWrapper app, TWIdentityWrapper ds, MSG msg, ref TW_SETUPFILEXFER data) { - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, DAT.SETUPFILEXFER, msg, ref data); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, DAT.SETUPFILEXFER, msg, ref data); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, DAT.SETUPFILEXFER, msg, ref data); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, DAT.SETUPFILEXFER, msg, ref data); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, DAT.SETUPFILEXFER, msg, ref data); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, DAT.SETUPFILEXFER, msg, ref data); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.CONTROL, DAT.SETUPFILEXFER, msg, ref data); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.CONTROL, DAT.SETUPFILEXFER, msg, ref data); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ControlDATs/SetupMemXfer.cs b/src/NTwain/Triplets/ControlDATs/SetupMemXfer.cs index 1e3195d..1234104 100644 --- a/src/NTwain/Triplets/ControlDATs/SetupMemXfer.cs +++ b/src/NTwain/Triplets/ControlDATs/SetupMemXfer.cs @@ -1,42 +1,39 @@ using NTwain.Data; using NTwain.DSM; -namespace NTwain.Triplets.ControlDATs +namespace NTwain.Triplets.ControlDATs; + +/// +/// Contains calls used with and . +/// +public class SetupMemXfer { - /// - /// Contains calls used with and . - /// - public class SetupMemXfer - { - public TWRC Get(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, out TW_SETUPMEMXFER data) + public TWRC Get(TWIdentityWrapper app, TWIdentityWrapper ds, out TW_SETUPMEMXFER data) { - data = default; - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + data = default; + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, DAT.SETUPMEMXFER, MSG.GET, ref data); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, DAT.SETUPMEMXFER, MSG.GET, ref data); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, DAT.SETUPMEMXFER, MSG.GET, ref data); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, DAT.SETUPMEMXFER, MSG.GET, ref data); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, DAT.SETUPMEMXFER, MSG.GET, ref data); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, DAT.SETUPMEMXFER, MSG.GET, ref data); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.CONTROL, DAT.SETUPMEMXFER, MSG.GET, ref data); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.CONTROL, DAT.SETUPMEMXFER, MSG.GET, ref data); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ControlDATs/Status.cs b/src/NTwain/Triplets/ControlDATs/Status.cs index 4dd4742..f8df012 100644 --- a/src/NTwain/Triplets/ControlDATs/Status.cs +++ b/src/NTwain/Triplets/ControlDATs/Status.cs @@ -2,72 +2,68 @@ using NTwain.DSM; using System; -namespace NTwain.Triplets.ControlDATs +namespace NTwain.Triplets.ControlDATs; + +/// +/// Contains calls used with and . +/// +public class Status { - /// - /// Contains calls used with and . - /// - public class Status - { - public TWRC GetForDSM(ref TW_IDENTITY_LEGACY app, out TW_STATUS status) + public TWRC GetForDSM(TWIdentityWrapper app, out TW_STATUS status) { - status = default; - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + status = default; + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, IntPtr.Zero, DG.CONTROL, DAT.STATUS, MSG.GET, ref status); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, IntPtr.Zero, DG.CONTROL, DAT.STATUS, MSG.GET, ref status); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, IntPtr.Zero, DG.CONTROL, DAT.STATUS, MSG.GET, ref status); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, IntPtr.Zero, DG.CONTROL, DAT.STATUS, MSG.GET, ref status); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, IntPtr.Zero, DG.CONTROL, DAT.STATUS, MSG.GET, ref status); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, IntPtr.Zero, DG.CONTROL, DAT.STATUS, MSG.GET, ref status); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, IntPtr.Zero, DG.CONTROL, DAT.STATUS, MSG.GET, ref status); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, IntPtr.Zero, DG.CONTROL, DAT.STATUS, MSG.GET, ref status); - } - } - return rc; + return rc; } - public TWRC GetForDS(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, out TW_STATUS status) + public TWRC GetForDS(TWIdentityWrapper app, TWIdentityWrapper ds, out TW_STATUS status) { - status = default; - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + status = default; + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, DAT.STATUS, MSG.GET, ref status); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, DAT.STATUS, MSG.GET, ref status); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, DAT.STATUS, MSG.GET, ref status); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, DAT.STATUS, MSG.GET, ref status); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, DAT.STATUS, MSG.GET, ref status); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, DAT.STATUS, MSG.GET, ref status); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX osxds = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref osxds, DG.CONTROL, DAT.STATUS, MSG.GET, ref status); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref osxds, DG.CONTROL, DAT.STATUS, MSG.GET, ref status); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ControlDATs/StatusUtf8.cs b/src/NTwain/Triplets/ControlDATs/StatusUtf8.cs index d2bff5c..1ecd742 100644 --- a/src/NTwain/Triplets/ControlDATs/StatusUtf8.cs +++ b/src/NTwain/Triplets/ControlDATs/StatusUtf8.cs @@ -2,13 +2,13 @@ using NTwain.DSM; using System; -namespace NTwain.Triplets.ControlDATs +namespace NTwain.Triplets.ControlDATs; + +/// +/// Contains calls used with and . +/// +public class StatusUtf8 { - /// - /// Contains calls used with and . - /// - public class StatusUtf8 - { /// /// Gets the extended text info for a previously received . /// If this is called you should try to extract the string value from it @@ -19,35 +19,33 @@ namespace NTwain.Triplets.ControlDATs /// /// /// - public TWRC Get(ref TW_IDENTITY_LEGACY app, TW_STATUS status, out TW_STATUSUTF8 extendedStatus) + public TWRC Get(TWIdentityWrapper app, TW_STATUS status, out TW_STATUSUTF8 extendedStatus) { - extendedStatus = new TW_STATUSUTF8 { Status = status }; - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + extendedStatus = new TW_STATUSUTF8 { Status = status }; + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, IntPtr.Zero, DG.CONTROL, DAT.STATUSUTF8, MSG.GET, ref extendedStatus); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, IntPtr.Zero, DG.CONTROL, DAT.STATUSUTF8, MSG.GET, ref extendedStatus); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, IntPtr.Zero, DG.CONTROL, DAT.STATUSUTF8, MSG.GET, ref extendedStatus); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, IntPtr.Zero, DG.CONTROL, DAT.STATUSUTF8, MSG.GET, ref extendedStatus); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, IntPtr.Zero, DG.CONTROL, DAT.STATUSUTF8, MSG.GET, ref extendedStatus); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, IntPtr.Zero, DG.CONTROL, DAT.STATUSUTF8, MSG.GET, ref extendedStatus); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, IntPtr.Zero, DG.CONTROL, DAT.STATUSUTF8, MSG.GET, ref extendedStatus); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, IntPtr.Zero, DG.CONTROL, DAT.STATUSUTF8, MSG.GET, ref extendedStatus); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ControlDATs/TwainDirect.cs b/src/NTwain/Triplets/ControlDATs/TwainDirect.cs index e8ca12f..52464a4 100644 --- a/src/NTwain/Triplets/ControlDATs/TwainDirect.cs +++ b/src/NTwain/Triplets/ControlDATs/TwainDirect.cs @@ -1,44 +1,41 @@ using NTwain.Data; using NTwain.DSM; -namespace NTwain.Triplets.ControlDATs -{ - /// - /// Contains calls used with and . - /// - public class TwainDirect - { - public TWRC SetTask(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_TWAINDIRECT data) - => DoIt(ref app, ref ds, MSG.SETTASK, ref data); +namespace NTwain.Triplets.ControlDATs; - static TWRC DoIt(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, MSG msg, ref TW_TWAINDIRECT data) +/// +/// Contains calls used with and . +/// +public class TwainDirect +{ + public TWRC SetTask(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_TWAINDIRECT data) + => DoIt(app, ds, MSG.SETTASK, ref data); + + static TWRC DoIt(TWIdentityWrapper app, TWIdentityWrapper ds, MSG msg, ref TW_TWAINDIRECT data) { - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.CIECOLOR, msg, ref data); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.CIECOLOR, msg, ref data); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.CIECOLOR, msg, ref data); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.CIECOLOR, msg, ref data); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.CIECOLOR, msg, ref data); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.CIECOLOR, msg, ref data); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.CIECOLOR, msg, ref data); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.CIECOLOR, msg, ref data); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ControlDATs/UserInterface.cs b/src/NTwain/Triplets/ControlDATs/UserInterface.cs index 526aabf..7b28300 100644 --- a/src/NTwain/Triplets/ControlDATs/UserInterface.cs +++ b/src/NTwain/Triplets/ControlDATs/UserInterface.cs @@ -1,50 +1,47 @@ using NTwain.Data; using NTwain.DSM; -namespace NTwain.Triplets.ControlDATs +namespace NTwain.Triplets.ControlDATs; + +/// +/// Contains calls used with and . +/// +public class UserInterface { - /// - /// Contains calls used with and . - /// - public class UserInterface - { - public TWRC DisableDS(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_USERINTERFACE data) - => DoIt(ref app, ref ds, MSG.DISABLEDS, ref data); + public TWRC DisableDS(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_USERINTERFACE data) + => DoIt(app, ds, MSG.DISABLEDS, ref data); - public TWRC EnableDS(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_USERINTERFACE data) - => DoIt(ref app, ref ds, MSG.ENABLEDS, ref data); + public TWRC EnableDS(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_USERINTERFACE data) + => DoIt(app, ds, MSG.ENABLEDS, ref data); - public TWRC EnableDSUIOnly(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_USERINTERFACE data) - => DoIt(ref app, ref ds, MSG.ENABLEDSUIONLY, ref data); + public TWRC EnableDSUIOnly(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_USERINTERFACE data) + => DoIt(app, ds, MSG.ENABLEDSUIONLY, ref data); - static TWRC DoIt(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, MSG msg, ref TW_USERINTERFACE data) + static TWRC DoIt(TWIdentityWrapper app, TWIdentityWrapper ds, MSG msg, ref TW_USERINTERFACE data) { - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, DAT.USERINTERFACE, msg, ref data); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, DAT.USERINTERFACE, msg, ref data); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, DAT.USERINTERFACE, msg, ref data); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, DAT.USERINTERFACE, msg, ref data); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, DAT.USERINTERFACE, msg, ref data); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, DAT.USERINTERFACE, msg, ref data); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.CONTROL, DAT.USERINTERFACE, msg, ref data); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.CONTROL, DAT.USERINTERFACE, msg, ref data); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ControlDATs/XferGroup.cs b/src/NTwain/Triplets/ControlDATs/XferGroup.cs index f49a85f..617388c 100644 --- a/src/NTwain/Triplets/ControlDATs/XferGroup.cs +++ b/src/NTwain/Triplets/ControlDATs/XferGroup.cs @@ -1,52 +1,49 @@ using NTwain.Data; using NTwain.DSM; -namespace NTwain.Triplets.ControlDATs +namespace NTwain.Triplets.ControlDATs; + +/// +/// Contains calls used with and . +/// +public class XferGroup { - /// - /// Contains calls used with and . - /// - public class XferGroup - { - public TWRC Get(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, out DG data) + public TWRC Get(TWIdentityWrapper app, TWIdentityWrapper ds, out DG data) { - data = default; - return DoIt(ref app, ref ds, MSG.GET, ref data); + data = default; + return DoIt(app, ds, MSG.GET, ref data); } - public TWRC Set(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, DG data) + public TWRC Set(TWIdentityWrapper app, TWIdentityWrapper ds, DG data) { - return DoIt(ref app, ref ds, MSG.SET, ref data); + return DoIt(app, ds, MSG.SET, ref data); } - static TWRC DoIt(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, MSG msg, ref DG data) + static TWRC DoIt(TWIdentityWrapper app, TWIdentityWrapper ds, MSG msg, ref DG data) { - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, DAT.XFERGROUP, msg, ref data); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, DAT.XFERGROUP, msg, ref data); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.CONTROL, DAT.XFERGROUP, msg, ref data); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.CONTROL, DAT.XFERGROUP, msg, ref data); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, DAT.XFERGROUP, msg, ref data); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.CONTROL, DAT.XFERGROUP, msg, ref data); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.CONTROL, DAT.XFERGROUP, msg, ref data); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.CONTROL, DAT.XFERGROUP, msg, ref data); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/DGAudio.cs b/src/NTwain/Triplets/DGAudio.cs index 9fa7f8c..36f4fc7 100644 --- a/src/NTwain/Triplets/DGAudio.cs +++ b/src/NTwain/Triplets/DGAudio.cs @@ -1,18 +1,17 @@ using NTwain.Data; using NTwain.Triplets.AudioDATs; -namespace NTwain.Triplets +namespace NTwain.Triplets; + +/// +/// Contains triplet calls starting with . +/// +public static class DGAudio { - /// - /// Contains triplet calls starting with . - /// - public static class DGAudio - { public static readonly AudioFileXfer AudioFileXfer = new(); public static readonly AudioInfo AudioInfo = new(); public static readonly AudioNativeXfer AudioNativeXfer = new(); - } } \ No newline at end of file diff --git a/src/NTwain/Triplets/ImageDATs/CieColor.cs b/src/NTwain/Triplets/ImageDATs/CieColor.cs index c85da26..51c4aa1 100644 --- a/src/NTwain/Triplets/ImageDATs/CieColor.cs +++ b/src/NTwain/Triplets/ImageDATs/CieColor.cs @@ -1,45 +1,42 @@ using NTwain.Data; using NTwain.DSM; -namespace NTwain.Triplets.ImageDATs -{ - /// - /// Contains calls used with and . - /// - public class CieColor - { - public TWRC Get(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, out TW_CIECOLOR data) - => DoIt(ref app, ref ds, MSG.GET, out data); +namespace NTwain.Triplets.ImageDATs; - static TWRC DoIt(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, MSG msg, out TW_CIECOLOR data) +/// +/// Contains calls used with and . +/// +public class CieColor +{ + public TWRC Get(TWIdentityWrapper app, TWIdentityWrapper ds, out TW_CIECOLOR data) + => DoIt(app, ds, MSG.GET, out data); + + static TWRC DoIt(TWIdentityWrapper app, TWIdentityWrapper ds, MSG msg, out TW_CIECOLOR data) { - var rc = TWRC.FAILURE; - data = default; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + data = default; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.CIECOLOR, msg, ref data); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.CIECOLOR, msg, ref data); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.CIECOLOR, msg, ref data); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.CIECOLOR, msg, ref data); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.CIECOLOR, msg, ref data); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.CIECOLOR, msg, ref data); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.CIECOLOR, msg, ref data); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.CIECOLOR, msg, ref data); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ImageDATs/ExtImageInfo.cs b/src/NTwain/Triplets/ImageDATs/ExtImageInfo.cs index 52f603d..a16e3c0 100644 --- a/src/NTwain/Triplets/ImageDATs/ExtImageInfo.cs +++ b/src/NTwain/Triplets/ImageDATs/ExtImageInfo.cs @@ -16,31 +16,29 @@ public class ExtImageInfo /// /// /// - public TWRC Get(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_EXTIMAGEINFO data) + public TWRC Get(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_EXTIMAGEINFO data) { var rc = TWRC.FAILURE; if (TWPlatform.IsWindows) { if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.EXTIMAGEINFO, MSG.GET, ref data); + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.EXTIMAGEINFO, MSG.GET, ref data); } else { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.EXTIMAGEINFO, MSG.GET, ref data); + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.EXTIMAGEINFO, MSG.GET, ref data); } } else if (TWPlatform.IsMacOSX) { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; if (TWPlatform.PreferLegacyDSM) { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.EXTIMAGEINFO, MSG.GET, ref data); + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.EXTIMAGEINFO, MSG.GET, ref data); } else { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.EXTIMAGEINFO, MSG.GET, ref data); + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.EXTIMAGEINFO, MSG.GET, ref data); } } return rc; @@ -53,31 +51,29 @@ public class ExtImageInfo /// /// /// - public TWRC GetSpecial(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_EXTIMAGEINFO data) + public TWRC GetSpecial(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_EXTIMAGEINFO data) { var rc = TWRC.FAILURE; if (TWPlatform.IsWindows) { if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.EXTIMAGEINFO, (MSG)KDS_MSG.GETSPECIAL, ref data); + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.EXTIMAGEINFO, (MSG)KDS_MSG.GETSPECIAL, ref data); } else { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.EXTIMAGEINFO, (MSG)KDS_MSG.GETSPECIAL, ref data); + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.EXTIMAGEINFO, (MSG)KDS_MSG.GETSPECIAL, ref data); } } else if (TWPlatform.IsMacOSX) { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; if (TWPlatform.PreferLegacyDSM) { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.EXTIMAGEINFO, (MSG)KDS_MSG.GETSPECIAL, ref data); + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.EXTIMAGEINFO, (MSG)KDS_MSG.GETSPECIAL, ref data); } else { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.EXTIMAGEINFO, (MSG)KDS_MSG.GETSPECIAL, ref data); + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.EXTIMAGEINFO, (MSG)KDS_MSG.GETSPECIAL, ref data); } } return rc; diff --git a/src/NTwain/Triplets/ImageDATs/Filter.cs b/src/NTwain/Triplets/ImageDATs/Filter.cs index bb42d47..9e31f5f 100644 --- a/src/NTwain/Triplets/ImageDATs/Filter.cs +++ b/src/NTwain/Triplets/ImageDATs/Filter.cs @@ -1,59 +1,56 @@ using NTwain.Data; using NTwain.DSM; -namespace NTwain.Triplets.ImageDATs +namespace NTwain.Triplets.ImageDATs; + +/// +/// Contains calls used with and . +/// +public class Filter { - /// - /// Contains calls used with and . - /// - public class Filter - { - public TWRC Get(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, out TW_FILTER data) + public TWRC Get(TWIdentityWrapper app, TWIdentityWrapper ds, out TW_FILTER data) { - data = default; - return DoIt(ref app, ref ds, MSG.GET, ref data); + data = default; + return DoIt(app, ds, MSG.GET, ref data); } - public TWRC GetDefault(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, out TW_FILTER data) + public TWRC GetDefault(TWIdentityWrapper app, TWIdentityWrapper ds, out TW_FILTER data) { - data = default; - return DoIt(ref app, ref ds, MSG.GETDEFAULT, ref data); + data = default; + return DoIt(app, ds, MSG.GETDEFAULT, ref data); } - public TWRC Set(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_FILTER data) - => DoIt(ref app, ref ds, MSG.SET, ref data); - public TWRC Reset(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, out TW_FILTER data) + public TWRC Set(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_FILTER data) + => DoIt(app, ds, MSG.SET, ref data); + public TWRC Reset(TWIdentityWrapper app, TWIdentityWrapper ds, out TW_FILTER data) { - data = default; - return DoIt(ref app, ref ds, MSG.RESET, ref data); + data = default; + return DoIt(app, ds, MSG.RESET, ref data); } - static TWRC DoIt(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, MSG msg, ref TW_FILTER data) + static TWRC DoIt(TWIdentityWrapper app, TWIdentityWrapper ds, MSG msg, ref TW_FILTER data) { - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.FILTER, msg, ref data); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.FILTER, msg, ref data); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.FILTER, msg, ref data); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.FILTER, msg, ref data); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.FILTER, msg, ref data); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.FILTER, msg, ref data); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.FILTER, msg, ref data); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.FILTER, msg, ref data); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ImageDATs/GrayResponse.cs b/src/NTwain/Triplets/ImageDATs/GrayResponse.cs index 13b810d..7fe4372 100644 --- a/src/NTwain/Triplets/ImageDATs/GrayResponse.cs +++ b/src/NTwain/Triplets/ImageDATs/GrayResponse.cs @@ -1,49 +1,46 @@ using NTwain.Data; using NTwain.DSM; -namespace NTwain.Triplets.ImageDATs +namespace NTwain.Triplets.ImageDATs; + +/// +/// Contains calls used with and . +/// +public class GrayResponse { - /// - /// Contains calls used with and . - /// - public class GrayResponse - { - public TWRC Set(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_GRAYRESPONSE data) - => DoIt(ref app, ref ds, MSG.SET, ref data); - public TWRC Reset(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, out TW_GRAYRESPONSE data) + public TWRC Set(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_GRAYRESPONSE data) + => DoIt(app, ds, MSG.SET, ref data); + public TWRC Reset(TWIdentityWrapper app, TWIdentityWrapper ds, out TW_GRAYRESPONSE data) { - data = default; - return DoIt(ref app, ref ds, MSG.RESET, ref data); + data = default; + return DoIt(app, ds, MSG.RESET, ref data); } - static TWRC DoIt(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, MSG msg, ref TW_GRAYRESPONSE data) + static TWRC DoIt(TWIdentityWrapper app, TWIdentityWrapper ds, MSG msg, ref TW_GRAYRESPONSE data) { - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.GRAYRESPONSE, msg, ref data); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.GRAYRESPONSE, msg, ref data); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.GRAYRESPONSE, msg, ref data); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.GRAYRESPONSE, msg, ref data); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.GRAYRESPONSE, msg, ref data); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.GRAYRESPONSE, msg, ref data); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.GRAYRESPONSE, msg, ref data); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.GRAYRESPONSE, msg, ref data); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ImageDATs/IccProfile.cs b/src/NTwain/Triplets/ImageDATs/IccProfile.cs index 6479acc..da22067 100644 --- a/src/NTwain/Triplets/ImageDATs/IccProfile.cs +++ b/src/NTwain/Triplets/ImageDATs/IccProfile.cs @@ -1,45 +1,42 @@ using NTwain.Data; using NTwain.DSM; -namespace NTwain.Triplets.ImageDATs -{ - /// - /// Contains calls used with and . - /// - public class IccProfile - { - public TWRC Get(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, out TW_MEMORY data) - => DoIt(ref app, ref ds, MSG.GET, out data); +namespace NTwain.Triplets.ImageDATs; - static TWRC DoIt(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, MSG msg, out TW_MEMORY data) +/// +/// Contains calls used with and . +/// +public class IccProfile +{ + public TWRC Get(TWIdentityWrapper app, TWIdentityWrapper ds, out TW_MEMORY data) + => DoIt(app, ds, MSG.GET, out data); + + static TWRC DoIt(TWIdentityWrapper app, TWIdentityWrapper ds, MSG msg, out TW_MEMORY data) { - var rc = TWRC.FAILURE; - data = default; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + data = default; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.ICCPROFILE, msg, ref data); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.ICCPROFILE, msg, ref data); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.ICCPROFILE, msg, ref data); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.ICCPROFILE, msg, ref data); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.ICCPROFILE, msg, ref data); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.ICCPROFILE, msg, ref data); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.ICCPROFILE, msg, ref data); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.ICCPROFILE, msg, ref data); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ImageDATs/ImageFileXfer.cs b/src/NTwain/Triplets/ImageDATs/ImageFileXfer.cs index c7a7904..f308a2d 100644 --- a/src/NTwain/Triplets/ImageDATs/ImageFileXfer.cs +++ b/src/NTwain/Triplets/ImageDATs/ImageFileXfer.cs @@ -2,44 +2,41 @@ using NTwain.DSM; using System; -namespace NTwain.Triplets.ImageDATs -{ - /// - /// Contains calls used with and . - /// - public class ImageFileXfer - { - public TWRC Get(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds) - => DoIt(ref app, ref ds, MSG.GET); +namespace NTwain.Triplets.ImageDATs; - static TWRC DoIt(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, MSG msg) +/// +/// Contains calls used with and . +/// +public class ImageFileXfer +{ + public TWRC Get(TWIdentityWrapper app, TWIdentityWrapper ds) + => DoIt(app, ds, MSG.GET); + + static TWRC DoIt(TWIdentityWrapper app, TWIdentityWrapper ds, MSG msg) { - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.IMAGEFILEXFER, msg, IntPtr.Zero); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.IMAGEFILEXFER, msg, IntPtr.Zero); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.IMAGEFILEXFER, msg, IntPtr.Zero); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.IMAGEFILEXFER, msg, IntPtr.Zero); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.IMAGEFILEXFER, msg, IntPtr.Zero); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.IMAGEFILEXFER, msg, IntPtr.Zero); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.IMAGEFILEXFER, msg, IntPtr.Zero); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.IMAGEFILEXFER, msg, IntPtr.Zero); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ImageDATs/ImageInfo.cs b/src/NTwain/Triplets/ImageDATs/ImageInfo.cs index b8aff50..f8f5488 100644 --- a/src/NTwain/Triplets/ImageDATs/ImageInfo.cs +++ b/src/NTwain/Triplets/ImageDATs/ImageInfo.cs @@ -1,45 +1,42 @@ using NTwain.Data; using NTwain.DSM; -namespace NTwain.Triplets.ImageDATs -{ - /// - /// Contains calls used with and . - /// - public class ImageInfo - { - public TWRC Get(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, out TW_IMAGEINFO data) - => DoIt(ref app, ref ds, MSG.GET, out data); +namespace NTwain.Triplets.ImageDATs; - static TWRC DoIt(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, MSG msg, out TW_IMAGEINFO data) +/// +/// Contains calls used with and . +/// +public class ImageInfo +{ + public TWRC Get(TWIdentityWrapper app, TWIdentityWrapper ds, out TW_IMAGEINFO data) + => DoIt(app, ds, MSG.GET, out data); + + static TWRC DoIt(TWIdentityWrapper app, TWIdentityWrapper ds, MSG msg, out TW_IMAGEINFO data) { - var rc = TWRC.FAILURE; - data = default; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + data = default; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.IMAGEINFO, msg, ref data); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.IMAGEINFO, msg, ref data); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.IMAGEINFO, msg, ref data); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.IMAGEINFO, msg, ref data); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.IMAGEINFO, msg, ref data); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.IMAGEINFO, msg, ref data); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.IMAGEINFO, msg, ref data); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.IMAGEINFO, msg, ref data); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ImageDATs/ImageLayout.cs b/src/NTwain/Triplets/ImageDATs/ImageLayout.cs index 4c94345..2aa8447 100644 --- a/src/NTwain/Triplets/ImageDATs/ImageLayout.cs +++ b/src/NTwain/Triplets/ImageDATs/ImageLayout.cs @@ -1,59 +1,56 @@ using NTwain.Data; using NTwain.DSM; -namespace NTwain.Triplets.ImageDATs +namespace NTwain.Triplets.ImageDATs; + +/// +/// Contains calls used with and . +/// +public class ImageLayout { - /// - /// Contains calls used with and . - /// - public class ImageLayout - { - public TWRC Get(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, out TW_IMAGELAYOUT data) + public TWRC Get(TWIdentityWrapper app, TWIdentityWrapper ds, out TW_IMAGELAYOUT data) { - data = default; - return DoIt(ref app, ref ds, MSG.GET, ref data); + data = default; + return DoIt(app, ds, MSG.GET, ref data); } - public TWRC GetDefault(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, out TW_IMAGELAYOUT data) + public TWRC GetDefault(TWIdentityWrapper app, TWIdentityWrapper ds, out TW_IMAGELAYOUT data) { - data = default; - return DoIt(ref app, ref ds, MSG.GETDEFAULT, ref data); + data = default; + return DoIt(app, ds, MSG.GETDEFAULT, ref data); } - public TWRC Set(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_IMAGELAYOUT data) - => DoIt(ref app, ref ds, MSG.SET, ref data); - public TWRC Reset(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, out TW_IMAGELAYOUT data) + public TWRC Set(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_IMAGELAYOUT data) + => DoIt(app, ds, MSG.SET, ref data); + public TWRC Reset(TWIdentityWrapper app, TWIdentityWrapper ds, out TW_IMAGELAYOUT data) { - data = default; - return DoIt(ref app, ref ds, MSG.RESET, ref data); + data = default; + return DoIt(app, ds, MSG.RESET, ref data); } - static TWRC DoIt(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, MSG msg, ref TW_IMAGELAYOUT data) + static TWRC DoIt(TWIdentityWrapper app, TWIdentityWrapper ds, MSG msg, ref TW_IMAGELAYOUT data) { - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.IMAGELAYOUT, msg, ref data); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.IMAGELAYOUT, msg, ref data); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.IMAGELAYOUT, msg, ref data); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.IMAGELAYOUT, msg, ref data); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.IMAGELAYOUT, msg, ref data); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.IMAGELAYOUT, msg, ref data); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.IMAGELAYOUT, msg, ref data); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.IMAGELAYOUT, msg, ref data); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ImageDATs/ImageMemFileXfer.cs b/src/NTwain/Triplets/ImageDATs/ImageMemFileXfer.cs index a74dc9b..0348c07 100644 --- a/src/NTwain/Triplets/ImageDATs/ImageMemFileXfer.cs +++ b/src/NTwain/Triplets/ImageDATs/ImageMemFileXfer.cs @@ -1,48 +1,45 @@ using NTwain.Data; using NTwain.DSM; -namespace NTwain.Triplets.ImageDATs +namespace NTwain.Triplets.ImageDATs; + +/// +/// Contains calls used with and . +/// +public class ImageMemFileXfer { - /// - /// Contains calls used with and . - /// - public class ImageMemFileXfer - { - public TWRC Get(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_IMAGEMEMXFER data) + public TWRC Get(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_IMAGEMEMXFER data) { - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.IMAGEMEMFILEXFER, MSG.GET, ref data); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.IMAGEMEMFILEXFER, MSG.GET, ref data); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.IMAGEMEMFILEXFER, MSG.GET, ref data); + } } - else - { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.IMAGEMEMFILEXFER, MSG.GET, ref data); - } - } - return rc; + return rc; } - public TWRC Get(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_IMAGEMEMXFER_MACOSX data) + public TWRC Get(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_IMAGEMEMXFER_MACOSX data) { - var rc = TWRC.FAILURE; - if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + if (TWPlatform.IsMacOSX) { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.IMAGEMEMXFER, MSG.GET, ref data); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.IMAGEMEMXFER, MSG.GET, ref data); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.IMAGEMEMXFER, MSG.GET, ref data); + } } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.IMAGEMEMXFER, MSG.GET, ref data); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ImageDATs/ImageMemXfer.cs b/src/NTwain/Triplets/ImageDATs/ImageMemXfer.cs index 47053a7..d5463f8 100644 --- a/src/NTwain/Triplets/ImageDATs/ImageMemXfer.cs +++ b/src/NTwain/Triplets/ImageDATs/ImageMemXfer.cs @@ -1,47 +1,44 @@ using NTwain.Data; using NTwain.DSM; -namespace NTwain.Triplets.ImageDATs +namespace NTwain.Triplets.ImageDATs; + +/// +/// Contains calls used with and . +/// +public class ImageMemXfer { - /// - /// Contains calls used with and . - /// - public class ImageMemXfer - { - public TWRC Get(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_IMAGEMEMXFER data) + public TWRC Get(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_IMAGEMEMXFER data) { - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.IMAGEMEMXFER, MSG.GET, ref data); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.IMAGEMEMXFER, MSG.GET, ref data); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.IMAGEMEMXFER, MSG.GET, ref data); + } } - else - { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.IMAGEMEMXFER, MSG.GET, ref data); - } - } - return rc; + return rc; } - public TWRC Get(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_IMAGEMEMXFER_MACOSX data) + public TWRC Get(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_IMAGEMEMXFER_MACOSX data) { - var rc = TWRC.FAILURE; - if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + if (TWPlatform.IsMacOSX) { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.IMAGEMEMXFER, MSG.GET, ref data); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.IMAGEMEMXFER, MSG.GET, ref data); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.IMAGEMEMXFER, MSG.GET, ref data); + } } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.IMAGEMEMXFER, MSG.GET, ref data); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ImageDATs/ImageNativeXfer.cs b/src/NTwain/Triplets/ImageDATs/ImageNativeXfer.cs index 8bb6f95..0ed9461 100644 --- a/src/NTwain/Triplets/ImageDATs/ImageNativeXfer.cs +++ b/src/NTwain/Triplets/ImageDATs/ImageNativeXfer.cs @@ -2,45 +2,42 @@ using NTwain.DSM; using System; -namespace NTwain.Triplets.ImageDATs -{ - /// - /// Contains calls used with and . - /// - public class ImageNativeXfer - { - public TWRC Get(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, out IntPtr data) - => DoIt(ref app, ref ds, MSG.GET, out data); +namespace NTwain.Triplets.ImageDATs; - static TWRC DoIt(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, MSG msg, out IntPtr data) +/// +/// Contains calls used with and . +/// +public class ImageNativeXfer +{ + public TWRC Get(TWIdentityWrapper app, TWIdentityWrapper ds, out IntPtr data) + => DoIt(app, ds, MSG.GET, out data); + + static TWRC DoIt(TWIdentityWrapper app, TWIdentityWrapper ds, MSG msg, out IntPtr data) { - var rc = TWRC.FAILURE; - data = IntPtr.Zero; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + data = IntPtr.Zero; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.IMAGENATIVEXFER, msg, ref data); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.IMAGENATIVEXFER, msg, ref data); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.IMAGENATIVEXFER, msg, ref data); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.IMAGENATIVEXFER, msg, ref data); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.IMAGENATIVEXFER, msg, ref data); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.IMAGENATIVEXFER, msg, ref data); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.IMAGENATIVEXFER, msg, ref data); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.IMAGENATIVEXFER, msg, ref data); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ImageDATs/JpegCompression.cs b/src/NTwain/Triplets/ImageDATs/JpegCompression.cs index 3612159..974e297 100644 --- a/src/NTwain/Triplets/ImageDATs/JpegCompression.cs +++ b/src/NTwain/Triplets/ImageDATs/JpegCompression.cs @@ -1,59 +1,56 @@ using NTwain.Data; using NTwain.DSM; -namespace NTwain.Triplets.ImageDATs +namespace NTwain.Triplets.ImageDATs; + +/// +/// Contains calls used with and . +/// +public class JpegCompression { - /// - /// Contains calls used with and . - /// - public class JpegCompression - { - public TWRC Get(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, out TW_JPEGCOMPRESSION data) + public TWRC Get(TWIdentityWrapper app, TWIdentityWrapper ds, out TW_JPEGCOMPRESSION data) { - data = default; - return DoIt(ref app, ref ds, MSG.GET, ref data); + data = default; + return DoIt(app, ds, MSG.GET, ref data); } - public TWRC GetDefault(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, out TW_JPEGCOMPRESSION data) + public TWRC GetDefault(TWIdentityWrapper app, TWIdentityWrapper ds, out TW_JPEGCOMPRESSION data) { - data = default; - return DoIt(ref app, ref ds, MSG.GETDEFAULT, ref data); + data = default; + return DoIt(app, ds, MSG.GETDEFAULT, ref data); } - public TWRC Set(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_JPEGCOMPRESSION data) - => DoIt(ref app, ref ds, MSG.SET, ref data); - public TWRC Reset(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, out TW_JPEGCOMPRESSION data) + public TWRC Set(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_JPEGCOMPRESSION data) + => DoIt(app, ds, MSG.SET, ref data); + public TWRC Reset(TWIdentityWrapper app, TWIdentityWrapper ds, out TW_JPEGCOMPRESSION data) { - data = default; - return DoIt(ref app, ref ds, MSG.RESET, ref data); + data = default; + return DoIt(app, ds, MSG.RESET, ref data); } - static TWRC DoIt(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, MSG msg, ref TW_JPEGCOMPRESSION data) + static TWRC DoIt(TWIdentityWrapper app, TWIdentityWrapper ds, MSG msg, ref TW_JPEGCOMPRESSION data) { - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.JPEGCOMPRESSION, msg, ref data); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.JPEGCOMPRESSION, msg, ref data); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.JPEGCOMPRESSION, msg, ref data); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.JPEGCOMPRESSION, msg, ref data); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.JPEGCOMPRESSION, msg, ref data); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.JPEGCOMPRESSION, msg, ref data); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.JPEGCOMPRESSION, msg, ref data); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.JPEGCOMPRESSION, msg, ref data); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ImageDATs/Palette8.cs b/src/NTwain/Triplets/ImageDATs/Palette8.cs index a87bd2e..96f28cf 100644 --- a/src/NTwain/Triplets/ImageDATs/Palette8.cs +++ b/src/NTwain/Triplets/ImageDATs/Palette8.cs @@ -1,59 +1,56 @@ using NTwain.Data; using NTwain.DSM; -namespace NTwain.Triplets.ImageDATs +namespace NTwain.Triplets.ImageDATs; + +/// +/// Contains calls used with and . +/// +public class Palette8 { - /// - /// Contains calls used with and . - /// - public class Palette8 - { - public TWRC Get(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, out TW_PALETTE8 data) + public TWRC Get(TWIdentityWrapper app, TWIdentityWrapper ds, out TW_PALETTE8 data) { - data = default; - return DoIt(ref app, ref ds, MSG.GET, ref data); + data = default; + return DoIt(app, ds, MSG.GET, ref data); } - public TWRC GetDefault(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, out TW_PALETTE8 data) + public TWRC GetDefault(TWIdentityWrapper app, TWIdentityWrapper ds, out TW_PALETTE8 data) { - data = default; - return DoIt(ref app, ref ds, MSG.GETDEFAULT, ref data); + data = default; + return DoIt(app, ds, MSG.GETDEFAULT, ref data); } - public TWRC Set(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_PALETTE8 data) - => DoIt(ref app, ref ds, MSG.SET, ref data); - public TWRC Reset(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, out TW_PALETTE8 data) + public TWRC Set(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_PALETTE8 data) + => DoIt(app, ds, MSG.SET, ref data); + public TWRC Reset(TWIdentityWrapper app, TWIdentityWrapper ds, out TW_PALETTE8 data) { - data = default; - return DoIt(ref app, ref ds, MSG.RESET, ref data); + data = default; + return DoIt(app, ds, MSG.RESET, ref data); } - static TWRC DoIt(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, MSG msg, ref TW_PALETTE8 data) + static TWRC DoIt(TWIdentityWrapper app, TWIdentityWrapper ds, MSG msg, ref TW_PALETTE8 data) { - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.PALETTE8, msg, ref data); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.PALETTE8, msg, ref data); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.PALETTE8, msg, ref data); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.PALETTE8, msg, ref data); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.PALETTE8, msg, ref data); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.PALETTE8, msg, ref data); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.PALETTE8, msg, ref data); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.PALETTE8, msg, ref data); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/Triplets/ImageDATs/RgbResponse.cs b/src/NTwain/Triplets/ImageDATs/RgbResponse.cs index 55d79c8..c538ca8 100644 --- a/src/NTwain/Triplets/ImageDATs/RgbResponse.cs +++ b/src/NTwain/Triplets/ImageDATs/RgbResponse.cs @@ -1,49 +1,46 @@ using NTwain.Data; using NTwain.DSM; -namespace NTwain.Triplets.ImageDATs +namespace NTwain.Triplets.ImageDATs; + +/// +/// Contains calls used with and . +/// +public class RgbResponse { - /// - /// Contains calls used with and . - /// - public class RgbResponse - { - public TWRC Set(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, ref TW_RGBRESPONSE data) - => DoIt(ref app, ref ds, MSG.SET, ref data); - public TWRC Reset(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, out TW_RGBRESPONSE data) + public TWRC Set(TWIdentityWrapper app, TWIdentityWrapper ds, ref TW_RGBRESPONSE data) + => DoIt(app, ds, MSG.SET, ref data); + public TWRC Reset(TWIdentityWrapper app, TWIdentityWrapper ds, out TW_RGBRESPONSE data) { - data = default; - return DoIt(ref app, ref ds, MSG.RESET, ref data); + data = default; + return DoIt(app, ds, MSG.RESET, ref data); } - static TWRC DoIt(ref TW_IDENTITY_LEGACY app, ref TW_IDENTITY_LEGACY ds, MSG msg, ref TW_RGBRESPONSE data) + static TWRC DoIt(TWIdentityWrapper app, TWIdentityWrapper ds, MSG msg, ref TW_RGBRESPONSE data) { - var rc = TWRC.FAILURE; - if (TWPlatform.IsWindows) - { - if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + var rc = TWRC.FAILURE; + if (TWPlatform.IsWindows) { - rc = WinLegacyDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.RGBRESPONSE, msg, ref data); + if (TWPlatform.Is32bit && TWPlatform.PreferLegacyDSM) + { + rc = WinLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.RGBRESPONSE, msg, ref data); + } + else + { + rc = WinNewDSM.DSM_Entry(ref app.TW_IDENTITY_LEGACY, ref ds.TW_IDENTITY_LEGACY, DG.IMAGE, DAT.RGBRESPONSE, msg, ref data); + } } - else + else if (TWPlatform.IsMacOSX) { - rc = WinNewDSM.DSM_Entry(ref app, ref ds, DG.IMAGE, DAT.RGBRESPONSE, msg, ref data); + if (TWPlatform.PreferLegacyDSM) + { + rc = OSXLegacyDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.RGBRESPONSE, msg, ref data); + } + else + { + rc = OSXNewDSM.DSM_Entry(ref app.TW_IDENTITY_MACOSX, ref ds.TW_IDENTITY_MACOSX, DG.IMAGE, DAT.RGBRESPONSE, msg, ref data); + } } - } - else if (TWPlatform.IsMacOSX) - { - TW_IDENTITY_MACOSX app2 = app; - TW_IDENTITY_MACOSX ds2 = ds; - if (TWPlatform.PreferLegacyDSM) - { - rc = OSXLegacyDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.RGBRESPONSE, msg, ref data); - } - else - { - rc = OSXNewDSM.DSM_Entry(ref app2, ref ds2, DG.IMAGE, DAT.RGBRESPONSE, msg, ref data); - } - } - return rc; + return rc; } - } } diff --git a/src/NTwain/TwainAppSession.Callback.cs b/src/NTwain/TwainAppSession.Callback.cs new file mode 100644 index 0000000..450da9f --- /dev/null +++ b/src/NTwain/TwainAppSession.Callback.cs @@ -0,0 +1,177 @@ +using Microsoft.Extensions.Logging; +using NTwain.Data; +using NTwain.Platform; +using NTwain.Triplets; +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using MSG = NTwain.Data.MSG; +using WinMSG = Windows.Win32.UI.WindowsAndMessaging.MSG; + +namespace NTwain; + + +// contains callback handling, from either the new registered callback function +// or the internal win32 message loop. + +partial class TwainAppSession : IWin32MessageFilter +{ + private bool _procEventHasData = false; + + /// + /// Used to check if a window message is for the TWAIN source. + /// + /// + /// + bool IWin32MessageFilter.PreFilterMessage(ref WinMSG winMsg) + { + // this handles the message from a typical WndProc message loop and checks if it's for the TWAIN source. + bool handled = false; + //if (_state >= STATE.S5) + //{ + + // if (!_closeDsRequested) + // { + if (_currentDs != null && _procEvent.pEvent != IntPtr.Zero) + { + Marshal.StructureToPtr(winMsg, _procEvent.pEvent, _procEventHasData); + _procEventHasData = true; + + var rc = DGControl.Event.ProcessEvent(_appIdentity, _currentDs, ref _procEvent); + handled = rc == TWRC.DSEVENT; + if (_procEvent.TWMessage != MSG.NULL && (handled || rc == TWRC.NOTDSEVENT)) + { + if (Logger.IsEnabled(LogLevel.Trace)) + Logger.LogTrace("[thread {ThreadId}] CheckIfTwainMessage at state {State} with MSG={Msg}.", + Environment.CurrentManagedThreadId, State, _procEvent.TWMessage); + HandleSourceMsg(_procEvent.TWMessage); + } + + } + return handled; + } + + + + + + + delegate ushort LegacyIDCallbackDelegate( + ref TW_IDENTITY_LEGACY origin, ref TW_IDENTITY_LEGACY dest, + DG dg, DAT dat, MSG msg, IntPtr twnull + ); + delegate ushort BotchedLinuxCallbackDelegate + ( + ref TW_IDENTITY origin, ref TW_IDENTITY dest, + DG dg, DAT dat, MSG msg, IntPtr twnull + ); + delegate ushort OSXCallbackDelegate + ( + ref TW_IDENTITY_MACOSX origin, ref TW_IDENTITY_MACOSX dest, + DG dg, DAT dat, MSG msg, IntPtr twnull + ); + + // these are kept around while a callback ptr is registered so they + // don't get gc'd + readonly LegacyIDCallbackDelegate _legacyCallbackDelegate; + readonly OSXCallbackDelegate _osxCallbackDelegate; + + /// + /// Try to registers callbacks for after opening the source. + /// + internal void RegisterCallback() + { + IntPtr cbPtr = IntPtr.Zero; + + if (TWPlatform.IsMacOSX) + { + cbPtr = Marshal.GetFunctionPointerForDelegate(_osxCallbackDelegate); + } + else + { + cbPtr = Marshal.GetFunctionPointerForDelegate(_legacyCallbackDelegate); + } + + if (cbPtr == IntPtr.Zero) + { + Logger.LogError("Failed to get callback function pointer."); + return; + } + + var rc = TWRC.FAILURE; + + // per the spec (pg 8-10), apps for 2.2 or higher uses callback2 so try this first + if (_appIdentity.ProtocolMajor > 2 || (_appIdentity.ProtocolMajor >= 2 && _appIdentity.ProtocolMinor >= 2)) + { + var cb2 = new TW_CALLBACK2 { CallBackProc = cbPtr }; + rc = DGControl.Callback2.RegisterCallback(_appIdentity, _currentDs!, ref cb2); + } + if (rc != TWRC.SUCCESS) + { + // always try old callback + var cb = new TW_CALLBACK { CallBackProc = cbPtr }; + DGControl.Callback.RegisterCallback(_appIdentity, _currentDs!, ref cb); + } + } + + private ushort LegacyCallbackHandler + ( + ref TW_IDENTITY_LEGACY origin, ref TW_IDENTITY_LEGACY dest, + DG dg, DAT dat, MSG msg, IntPtr twnull + ) + { + if (Logger.IsEnabled(LogLevel.Trace)) + Logger.LogTrace("Legacy callback got {Msg}", msg); + HandleSourceMsg(msg); + return (ushort)TWRC.SUCCESS; + } + + private ushort OSXCallbackHandler + ( + ref TW_IDENTITY_MACOSX origin, ref TW_IDENTITY_MACOSX dest, + DG dg, DAT dat, MSG msg, IntPtr twnull + ) + { + if (Logger.IsEnabled(LogLevel.Trace)) + Logger.LogTrace("OSX callback got {Msg}", msg); + HandleSourceMsg(msg); + return (ushort)TWRC.SUCCESS; + } + + private void HandleSourceMsg(MSG msg, [CallerMemberName] string? caller = null) + { + if (Logger.IsEnabled(LogLevel.Trace)) + Logger.LogTrace("[thread {ThreadId}] {Caller} called by {Caller} at state {State} with {Msg}.", + Environment.CurrentManagedThreadId, nameof(HandleSourceMsg), caller, State, msg); + + switch (msg) + { + case MSG.XFERREADY: + _transferThread.NotifyTransferReady(true); + break; + case MSG.CLOSEDSOK: // user click ok in driver-only dialog + DisableSource(); + break; + case MSG.CLOSEDSREQ: + if (EnabledWithOption == SourceEnableOption.UIOnly ||// user click cancel in driver dialog + !_transferThread.IsTransferring) + { + DisableSource(); + } + else + { + // set flag to cancel transfer and let it disable ds + _transferThread.CloseDsRequested = true; + } + break; + case MSG.DEVICEEVENT: + if (DeviceEvent != null && + _currentDs != null && + DGControl.DeviceEvent.Get(_appIdentity, _currentDs, out TW_DEVICEEVENT de) == TWRC.SUCCESS) + { + RaiseEvent(DeviceEvent, de); + } + break; + } + } +} \ No newline at end of file diff --git a/src/NTwain/TwainAppSession.Callbacks.cs b/src/NTwain/TwainAppSession.Callbacks.cs deleted file mode 100644 index 77dd184..0000000 --- a/src/NTwain/TwainAppSession.Callbacks.cs +++ /dev/null @@ -1,141 +0,0 @@ -using Microsoft.Extensions.Logging; -using NTwain.Data; -using NTwain.Triplets; -using System; -using System.Diagnostics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace NTwain -{ - // this file contains callback methods - - partial class TwainAppSession - { - - delegate ushort LegacyIDCallbackDelegate( - ref TW_IDENTITY_LEGACY origin, ref TW_IDENTITY_LEGACY dest, - DG dg, DAT dat, MSG msg, IntPtr twnull - ); - delegate ushort BotchedLinuxCallbackDelegate - ( - ref TW_IDENTITY origin, ref TW_IDENTITY dest, - DG dg, DAT dat, MSG msg, IntPtr twnull - ); - delegate ushort OSXCallbackDelegate - ( - ref TW_IDENTITY_MACOSX origin, ref TW_IDENTITY_MACOSX dest, - DG dg, DAT dat, MSG msg, IntPtr twnull - ); - - // these are kept around while a callback ptr is registered so they - // don't get gc'd - readonly LegacyIDCallbackDelegate _legacyCallbackDelegate; - readonly OSXCallbackDelegate _osxCallbackDelegate; - - /// - /// Try to registers callbacks for after opening the source. - /// - internal void RegisterCallback() - { - IntPtr cbPtr = IntPtr.Zero; - - if (TWPlatform.IsMacOSX) - { - cbPtr = Marshal.GetFunctionPointerForDelegate(_osxCallbackDelegate); - } - else - { - cbPtr = Marshal.GetFunctionPointerForDelegate(_legacyCallbackDelegate); - } - - var rc = TWRC.FAILURE; - - // per the spec (pg 8-10), apps for 2.2 or higher uses callback2 so try this first - if (_appIdentity.ProtocolMajor > 2 || (_appIdentity.ProtocolMajor >= 2 && _appIdentity.ProtocolMinor >= 2)) - { - var cb2 = new TW_CALLBACK2 { CallBackProc = cbPtr }; - rc = DGControl.Callback2.RegisterCallback(ref _appIdentity, ref _currentDS, ref cb2); - } - if (rc != TWRC.SUCCESS) - { - // always try old callback - var cb = new TW_CALLBACK { CallBackProc = cbPtr }; - DGControl.Callback.RegisterCallback(ref _appIdentity, ref _currentDS, ref cb); - } - } - - private ushort LegacyCallbackHandler - ( - ref TW_IDENTITY_LEGACY origin, ref TW_IDENTITY_LEGACY dest, - DG dg, DAT dat, MSG msg, IntPtr twnull - ) - { - Logger.LogTrace("Legacy callback got {Msg}", msg); - HandleSourceMsg(msg); - return (ushort)TWRC.SUCCESS; - } - - private ushort OSXCallbackHandler - ( - ref TW_IDENTITY_MACOSX origin, ref TW_IDENTITY_MACOSX dest, - DG dg, DAT dat, MSG msg, IntPtr twnull - ) - { - Logger.LogTrace("OSX callback got {Msg}", msg); - HandleSourceMsg(msg); - return (ushort)TWRC.SUCCESS; - } - - - private void HandleSourceMsg(MSG msg, [CallerMemberName] string? caller = null) - { - Logger.LogTrace("[thread {ThreadId}] {Caller} called by {Caller} at state {State} with {Msg}.", - Environment.CurrentManagedThreadId, nameof(HandleSourceMsg), caller, State, msg); - - // the reason we post these to the background is - // if they're coming from UI message loop then - // this needs to return asap - - switch (msg) - { - case MSG.XFERREADY: - if (_transferInCallbackThread) - { - EnterTransferRoutine(); - } - else - { - // use bg thread to process transfer. - // some sources spam this even during transfer so we gate it - if (!_inTransfer) - { - _inTransfer = true; - _xferReady.Set(); - //_bgPendingMsgs.Add(msg); - } - } - break; - case MSG.CLOSEDSOK: - case MSG.CLOSEDSREQ: - _closeDsRequested = true; - if (!_inTransfer) - { - // this should be done on ui thread (or same one that enabled the ds) - DisableSource(); - } - break; - case MSG.DEVICEEVENT: - if (DeviceEvent != null && DGControl.DeviceEvent.Get(ref _appIdentity, ref _currentDS, out TW_DEVICEEVENT de) == TWRC.SUCCESS) - { - try - { - DeviceEvent.Invoke(this, de); - } - catch { } - } - break; - } - } - } -} diff --git a/src/NTwain/TwainAppSession.Caps.cs b/src/NTwain/TwainAppSession.Caps.cs index 2c97eb9..1281905 100644 --- a/src/NTwain/TwainAppSession.Caps.cs +++ b/src/NTwain/TwainAppSession.Caps.cs @@ -6,735 +6,758 @@ using System.Collections.Generic; using System.Linq; using System.Text; -namespace NTwain +namespace NTwain; + +// this file contains capability mgmt methods + +// TODO: need to marshal to pump thread? + +partial class TwainAppSession { - // this file contains capability mgmt methods + private BuiltInCaps? _builtinCaps; - partial class TwainAppSession + /// + /// Access the built-in TWAIN caps as properties. + /// + public BuiltInCaps Caps { - private BuiltInCaps? _builtinCaps; + get { return _builtinCaps ??= new BuiltInCaps(this); } + } - /// - /// Access the built-in TWAIN caps as properties. - /// - public BuiltInCaps Caps + private KdsCaps? _kdsCaps; + + /// + /// Access the Kodak custom caps as properties. + /// + public KdsCaps KdsCaps + { + get { return _kdsCaps ??= new KdsCaps(this); } + } + + /// + /// Gets a CAP's actual supported operations. + /// This is not supported by all sources. + /// + /// + /// + public TWQC QueryCapSupport(CAP cap) + { + if (_currentDs == null) return TWQC.Unknown; + + var value = new TW_CAPABILITY(cap) { ConType = TWON.ONEVALUE }; + if (DGControl.Capability.QuerySupport(_appIdentity, _currentDs, ref value) == TWRC.SUCCESS) { - get { return _builtinCaps ??= new BuiltInCaps(this); } + return value.ReadOneValue(MemoryManager); } + return TWQC.Unknown; + } - private KdsCaps? _kdsCaps; + /// + /// Gets a CAP's raw current value. + /// Caller will need to manually read and free the memory. + /// + /// + /// + /// + public STS GetCapCurrent(CAP cap, out TW_CAPABILITY value) + { + value = new TW_CAPABILITY(cap); + if (_currentDs == null) return STS.SequenceError(); - /// - /// Access the Kodak custom caps as properties. - /// - public KdsCaps KdsCaps + return WrapInSTS(DGControl.Capability.GetCurrent(_appIdentity, _currentDs, ref value)); + } + + /// + /// Gets a CAP's current value. This is a simplified version that doesn't require + /// manual reading, but may or may not work. + /// + /// + /// + /// + /// + public STS GetCapCurrent(CAP cap, out List value) where TValue : struct + { + value = []; + var sts = GetCapCurrent(cap, out TW_CAPABILITY twcap); + if (sts.RC == TWRC.SUCCESS) { - get { return _kdsCaps ??= new KdsCaps(this); } - } - - /// - /// Gets a CAP's actual supported operations. - /// This is not supported by all sources. - /// - /// - /// - public TWQC QueryCapSupport(CAP cap) - { - var value = new TW_CAPABILITY(cap) { ConType = TWON.ONEVALUE }; - if (DGControl.Capability.QuerySupport(ref _appIdentity, ref _currentDS, ref value) == TWRC.SUCCESS) - { - return value.ReadOneValue(this); - } - return TWQC.Unknown; - } - - /// - /// Gets a CAP's raw current value. - /// Caller will need to manually read and free the memory. - /// - /// - /// - /// - public STS GetCapCurrent(CAP cap, out TW_CAPABILITY value) - { - value = new TW_CAPABILITY(cap); - return WrapInSTS(DGControl.Capability.GetCurrent(ref _appIdentity, ref _currentDS, ref value)); - } - - /// - /// Gets a CAP's current value. This is a simplified version that doesn't require - /// manual reading, but may or may not work. - /// - /// - /// - /// - /// - public STS GetCapCurrent(CAP cap, out List value) where TValue : struct - { - value = []; - var sts = GetCapCurrent(cap, out TW_CAPABILITY twcap); - if (sts.RC == TWRC.SUCCESS) - { - switch (twcap.ConType) - { - case TWON.ONEVALUE: - value.Add(twcap.ReadOneValue(this)); - break; - case TWON.ENUMERATION: - var twenum = twcap.ReadEnumeration(this); - if (twenum.Items != null && twenum.CurrentIndex < twenum.Items.Length) - { - value.Add(twenum.Items[twenum.CurrentIndex]); - } - break; - case TWON.RANGE: - var range = twcap.ReadRange(this); - if (range != null) value.Add(range.CurrentValue); - break; - case TWON.ARRAY: - var twarr = twcap.ReadArray(this); - if (twarr != null && twarr.Count > 0) value.AddRange(twarr); - break; - default: - twcap.Free(this); break; - } - } - return sts; - } - - /// - /// Gets a CAP's current value as boxed values. This is a simplified version that doesn't require - /// manual reading, but may or may not work. - /// - /// - /// - /// - public STS GetCapCurrentBoxed(CAP cap, out List value) - { - value = []; - var sts = GetCapCurrent(cap, out TW_CAPABILITY twcap); - if (sts.RC == TWRC.SUCCESS) - { - switch (twcap.ConType) - { - case TWON.ONEVALUE: - var read = twcap.ReadOneValueBoxed(this); - if (read != null) value.Add(read); - break; - case TWON.ENUMERATION: - var twenum = twcap.ReadEnumerationBoxed(this); - if (twenum.Items != null && twenum.CurrentIndex < twenum.Items.Length) - { - value.Add(twenum.Items[twenum.CurrentIndex]); - } - break; - case TWON.RANGE: - var range = twcap.ReadRangeBoxed(this); - if (range != null) value.Add(range.CurrentValue); - break; - case TWON.ARRAY: - var twarr = twcap.ReadArrayBoxed(this); - if (twarr != null && twarr.Count > 0) value.AddRange(twarr); - break; - default: - twcap.Free(this); break; - } - } - return sts; - } - - /// - /// Gets a CAP's raw default value. - /// Caller will need to manually read and free the memory. - /// - /// - /// - /// - public STS GetCapDefault(CAP cap, out TW_CAPABILITY value) - { - value = new TW_CAPABILITY(cap); - return WrapInSTS(DGControl.Capability.GetDefault(ref _appIdentity, ref _currentDS, ref value)); - } - - - /// - /// Gets a CAP's default value. This is a simplified version that doesn't require - /// manual reading, but may or may not work. - /// - /// - /// - /// - /// - public STS GetCapDefault(CAP cap, out List value) where TValue : struct - { - value = []; - var sts = GetCapDefault(cap, out TW_CAPABILITY twcap); - if (sts.RC == TWRC.SUCCESS) - { - switch (twcap.ConType) - { - case TWON.ONEVALUE: - value.Add(twcap.ReadOneValue(this)); - break; - case TWON.ENUMERATION: - var twenum = twcap.ReadEnumeration(this); - if (twenum.Items != null && twenum.DefaultIndex < twenum.Items.Length) - { - value.Add(twenum.Items[twenum.DefaultIndex]); - } - break; - case TWON.RANGE: - var range = twcap.ReadRange(this); - if (range != null) value.Add(range.DefaultValue); - break; - case TWON.ARRAY: - var twarr = twcap.ReadArray(this); - if (twarr != null && twarr.Count > 0) value.AddRange(twarr); - break; - default: - twcap.Free(this); break; - } - } - return sts; - } - - /// - /// Gets a CAP's default value. This is a simplified version that doesn't require - /// manual reading, but may or may not work. - /// - /// - /// - /// - public STS GetCapDefaultBoxed(CAP cap, out List value) - { - value = []; - var sts = GetCapDefault(cap, out TW_CAPABILITY twcap); - if (sts.RC == TWRC.SUCCESS) - { - switch (twcap.ConType) - { - case TWON.ONEVALUE: - var read = twcap.ReadOneValueBoxed(this); - if (read != null) value.Add(read); - break; - case TWON.ENUMERATION: - var twenum = twcap.ReadEnumerationBoxed(this); - if (twenum.Items != null && twenum.DefaultIndex < twenum.Items.Length) - { - value.Add(twenum.Items[twenum.DefaultIndex]); - } - break; - case TWON.RANGE: - var range = twcap.ReadRangeBoxed(this); - if (range != null) value.Add(range.DefaultValue); - break; - case TWON.ARRAY: - var twarr = twcap.ReadArrayBoxed(this); - if (twarr != null && twarr.Count > 0) value.AddRange(twarr); - break; - default: - twcap.Free(this); break; - } - } - return sts; - } - - /// - /// Gets a CAP's raw supported values. - /// Caller will need to manually read and free the memory. - /// - /// - /// - /// - public STS GetCapValues(CAP cap, out TW_CAPABILITY value) - { - value = new TW_CAPABILITY(cap); - return WrapInSTS(DGControl.Capability.Get(ref _appIdentity, ref _currentDS, ref value)); - } - - - /// - /// Gets a CAP's supported values. This is a simplified version that doesn't require - /// manual reading, but may or may not work. - /// - /// - /// - /// - /// - public STS GetCapValues(CAP cap, out ValueContainer value) where TValue : struct - { - value = new ValueContainer { ContainerType = TWON.DONTCARE }; - var sts = GetCapValues(cap, out TW_CAPABILITY twcap); - if (sts.RC == TWRC.SUCCESS) - { - value.ContainerType = twcap.ConType; - switch (twcap.ConType) - { - case TWON.ONEVALUE: - value.OneValue = twcap.ReadOneValue(this); - break; - case TWON.ENUMERATION: - var twenum = twcap.ReadEnumeration(this); - if (twenum.Items != null) - { - value.EnumValue = twenum; - } - break; - case TWON.RANGE: - var range = twcap.ReadRange(this); - value.RangeValue = range; - break; - case TWON.ARRAY: - var twarr = twcap.ReadArray(this); - if (twarr != null) - { - value.ArrayValue = twarr; - } - break; - default: - twcap.Free(this); break; - } - } - return sts; - } - - - /// - /// Gets a CAP's supported values. This is a simplified version that doesn't require - /// manual reading, but may or may not work. - /// - /// - /// - /// - public STS GetCapValuesBoxed(CAP cap, out ValueContainer value) - { - value = new ValueContainer { ContainerType = TWON.DONTCARE }; - var sts = GetCapValues(cap, out TW_CAPABILITY twcap); - if (sts.RC == TWRC.SUCCESS) - { - value.ContainerType = twcap.ConType; - switch (twcap.ConType) - { - case TWON.ONEVALUE: - value.OneValue = twcap.ReadOneValueBoxed(this); - break; - case TWON.ENUMERATION: - var twenum = twcap.ReadEnumerationBoxed(this); - if (twenum.Items != null) - { - value.EnumValue = twenum; - } - break; - case TWON.RANGE: - var range = twcap.ReadRangeBoxed(this); - value.RangeValue = range; - break; - case TWON.ARRAY: - var twarr = twcap.ReadArrayBoxed(this); - if (twarr != null) - { - value.ArrayValue = twarr; - } - break; - default: - twcap.Free(this); break; - } - } - return sts; - } - - /// - /// Gets a CAP's help text (description). - /// This may not work due to unclear spec. - /// - /// - /// - /// - public STS GetCapHelp(CAP cap, out string? help) - { - help = null; - var value = new TW_CAPABILITY(cap); - var rc = DGControl.Capability.GetHelp(ref _appIdentity, ref _currentDS, ref value); - if (rc == TWRC.SUCCESS) - { - help = value.ReadString(this, false); - } - value.Free(this); - return WrapInSTS(rc); - } - - /// - /// Gets a CAP's text name label. - /// This may not work due to unclear spec. - /// - /// - /// - /// - public STS GetCapLabel(CAP cap, out string? label) - { - label = null; - var value = new TW_CAPABILITY(cap) { ConType = TWON.ONEVALUE }; - var rc = DGControl.Capability.GetLabel(ref _appIdentity, ref _currentDS, ref value); - if (rc == TWRC.SUCCESS) - { - label = value.ReadString(this, false); - } - value.Free(this); - return WrapInSTS(rc); - } - - /// - /// Gets a CAP's enum/array value label texts. - /// - /// - /// - /// - public STS GetCapLabelEnum(CAP cap, out IList labels) - { - labels = Array.Empty(); - var value = new TW_CAPABILITY(cap); - var rc = DGControl.Capability.GetLabelEnum(ref _appIdentity, ref _currentDS, ref value); - if (rc == TWRC.SUCCESS) - { - // spec says they're utf8 - labels = value.ReadArray(this, false).Select(t => t.Get(Encoding.UTF8)).ToList(); - } - value.Free(this); - return WrapInSTS(rc); - } - - /// - /// Sets a CAP's current value. - /// An easy way to create a value is to use the - /// - /// extension method (or the other container variants). - /// Memory of the value will be freed afterwards. - /// - /// - /// - public STS SetCap(ref TW_CAPABILITY value) - { - var rc = DGControl.Capability.Set(ref _appIdentity, ref _currentDS, ref value); - value.Free(this); - - if (value.Cap == CAP.CAP_LANGUAGE && rc == TWRC.SUCCESS) - { - RefreshCapLanguage(); - } - - return WrapInSTS(rc); - } - - /// - /// A simpler cap value setter for one-value type. - /// - /// - /// - /// - /// - public STS SetCap(CAP cap, TValue value) where TValue : struct - { - var twcap = ValueWriter.CreateOneValueCap(cap, this, value); - return SetCap(ref twcap); - } - - /// - /// A cap value setter for enumeration container type. - /// - /// - /// - /// - /// - public STS SetCap(CAP cap, Enumeration value) where TValue : struct - { - var twcap = ValueWriter.CreateEnumCap(cap, this, value); - return SetCap(ref twcap); - } - - /// - /// A cap value setter for range container type. - /// - /// - /// - /// - /// - public STS SetCap(CAP cap, Range value) where TValue : struct - { - var twcap = ValueWriter.CreateRangeCap(cap, this, value); - return SetCap(ref twcap); - } - - /// - /// A cap value setter for array container type. - /// - /// - /// - /// - /// - public STS SetCap(CAP cap, IList value) where TValue : struct - { - var twcap = ValueWriter.CreateArrayCap(cap, this, value); - return SetCap(ref twcap); - } - - /// - /// A cap value setter for all kinds of container types. - /// - /// - /// - /// - /// - /// - public STS SetCap(CAP cap, ValueContainer value) where TValue : struct - { - switch (value.ContainerType) + switch (twcap.ConType) { case TWON.ONEVALUE: - return SetCap(cap, value.OneValue); + value.Add(twcap.ReadOneValue(MemoryManager)); + break; case TWON.ENUMERATION: - if (value.EnumValue == null) - throw new ArgumentException("EnumValue cannot be null when ContainerType is ENUMERATION.", nameof(value)); - return SetCap(cap, value.EnumValue); + var twenum = twcap.ReadEnumeration(MemoryManager); + if (twenum.Items != null && twenum.CurrentIndex < twenum.Items.Length) + { + value.Add(twenum.Items[twenum.CurrentIndex]); + } + break; case TWON.RANGE: - if (value.RangeValue == null) - throw new ArgumentException("RangeValue cannot be null when ContainerType is RANGE.", nameof(value)); - return SetCap(cap, value.RangeValue); + var range = twcap.ReadRange(MemoryManager); + if (range != null) value.Add(range.CurrentValue); + break; case TWON.ARRAY: - if (value.ArrayValue == null) - throw new ArgumentException("ArrayValue cannot be null when ContainerType is ARRAY.", nameof(value)); - return SetCap(cap, value.ArrayValue); + var twarr = twcap.ReadArray(MemoryManager); + if (twarr != null && twarr.Count > 0) value.AddRange(twarr); + break; default: - throw new ArgumentException("Unsupported ContainerType for setting CAP.", nameof(value)); + twcap.Free(MemoryManager); break; } } + return sts; + } - /// - /// Sets a CAP's constraint values. - /// An easy way to create a value is to use the - /// - /// extension method (or the other container variants). - /// Memory of the value will be freed afterwards. - /// - /// - /// - public STS SetConstraint(ref TW_CAPABILITY value) + /// + /// Gets a CAP's current value as boxed values. This is a simplified version that doesn't require + /// manual reading, but may or may not work. + /// + /// + /// + /// + public STS GetCapCurrentBoxed(CAP cap, out List value) + { + value = []; + var sts = GetCapCurrent(cap, out TW_CAPABILITY twcap); + if (sts.RC == TWRC.SUCCESS) { - var rc = DGControl.Capability.SetConstraint(ref _appIdentity, ref _currentDS, ref value); - value.Free(this); - return WrapInSTS(rc); - } - - - /// - /// A simpler cap constraint setter for one-value type. - /// - /// - /// - /// - /// - public STS SetConstraint(CAP cap, TValue value) where TValue : struct - { - var twcap = ValueWriter.CreateOneValueCap(cap, this, value); - return SetConstraint(ref twcap); - } - - /// - /// A cap constraint setter for enumeration container type. - /// - /// - /// - /// - /// - public STS SetConstraint(CAP cap, Enumeration value) where TValue : struct - { - var twcap = ValueWriter.CreateEnumCap(cap, this, value); - return SetConstraint(ref twcap); - } - - /// - /// A cap constraint setter for range container type. - /// - /// - /// - /// - /// - public STS SetConstraint(CAP cap, Range value) where TValue : struct - { - var twcap = ValueWriter.CreateRangeCap(cap, this, value); - return SetConstraint(ref twcap); - } - - /// - /// A cap constraint setter for array container type. - /// - /// - /// - /// - /// - public STS SetConstraint(CAP cap, IList value) where TValue : struct - { - var twcap = ValueWriter.CreateArrayCap(cap, this, value); - return SetConstraint(ref twcap); - } - - /// - /// A cap constraint setter for all kinds of container types. - /// - /// - /// - /// - /// - /// - public STS SetConstraint(CAP cap, ValueContainer value) where TValue : struct - { - switch (value.ContainerType) + switch (twcap.ConType) { case TWON.ONEVALUE: - return SetConstraint(cap, value.OneValue); + var read = twcap.ReadOneValueBoxed(MemoryManager); + if (read != null) value.Add(read); + break; case TWON.ENUMERATION: - if (value.EnumValue == null) - throw new ArgumentException("EnumValue cannot be null when ContainerType is ENUMERATION.", nameof(value)); - return SetConstraint(cap, value.EnumValue); + var twenum = twcap.ReadEnumerationBoxed(MemoryManager); + if (twenum.Items != null && twenum.CurrentIndex < twenum.Items.Length) + { + value.Add(twenum.Items[twenum.CurrentIndex]); + } + break; case TWON.RANGE: - if (value.RangeValue == null) - throw new ArgumentException("RangeValue cannot be null when ContainerType is RANGE.", nameof(value)); - return SetConstraint(cap, value.RangeValue); + var range = twcap.ReadRangeBoxed(MemoryManager); + if (range != null) value.Add(range.CurrentValue); + break; case TWON.ARRAY: - if (value.ArrayValue == null) - throw new ArgumentException("ArrayValue cannot be null when ContainerType is ARRAY.", nameof(value)); - return SetConstraint(cap, value.ArrayValue); + var twarr = twcap.ReadArrayBoxed(MemoryManager); + if (twarr != null && twarr.Count > 0) value.AddRange(twarr); + break; default: - throw new ArgumentException("Unsupported ContainerType for setting CAP constraint.", nameof(value)); + twcap.Free(MemoryManager); break; } } + return sts; + } - /// - /// Resets a CAP's current value to power-on default. - /// Caller will need to manually read and free the memory. - /// - /// - /// - /// - public STS ResetCap(CAP cap, out TW_CAPABILITY value) + /// + /// Gets a CAP's raw default value. + /// Caller will need to manually read and free the memory. + /// + /// + /// + /// + public STS GetCapDefault(CAP cap, out TW_CAPABILITY value) + { + value = new TW_CAPABILITY(cap); + if (_currentDs == null) return STS.SequenceError(); + + return WrapInSTS(DGControl.Capability.GetDefault(_appIdentity, _currentDs, ref value)); + } + + + /// + /// Gets a CAP's default value. This is a simplified version that doesn't require + /// manual reading, but may or may not work. + /// + /// + /// + /// + /// + public STS GetCapDefault(CAP cap, out List value) where TValue : struct + { + value = []; + var sts = GetCapDefault(cap, out TW_CAPABILITY twcap); + if (sts.RC == TWRC.SUCCESS) { - value = new TW_CAPABILITY(cap); - var rc = DGControl.Capability.Reset(ref _appIdentity, ref _currentDS, ref value); - - if (value.Cap == CAP.CAP_LANGUAGE && rc == TWRC.SUCCESS) + switch (twcap.ConType) { - RefreshCapLanguage(); + case TWON.ONEVALUE: + value.Add(twcap.ReadOneValue(MemoryManager)); + break; + case TWON.ENUMERATION: + var twenum = twcap.ReadEnumeration(MemoryManager); + if (twenum.Items != null && twenum.DefaultIndex < twenum.Items.Length) + { + value.Add(twenum.Items[twenum.DefaultIndex]); + } + break; + case TWON.RANGE: + var range = twcap.ReadRange(MemoryManager); + if (range != null) value.Add(range.DefaultValue); + break; + case TWON.ARRAY: + var twarr = twcap.ReadArray(MemoryManager); + if (twarr != null && twarr.Count > 0) value.AddRange(twarr); + break; + default: + twcap.Free(MemoryManager); break; } + } + return sts; + } - return WrapInSTS(rc); + /// + /// Gets a CAP's default value. This is a simplified version that doesn't require + /// manual reading, but may or may not work. + /// + /// + /// + /// + public STS GetCapDefaultBoxed(CAP cap, out List value) + { + value = []; + var sts = GetCapDefault(cap, out TW_CAPABILITY twcap); + if (sts.RC == TWRC.SUCCESS) + { + switch (twcap.ConType) + { + case TWON.ONEVALUE: + var read = twcap.ReadOneValueBoxed(MemoryManager); + if (read != null) value.Add(read); + break; + case TWON.ENUMERATION: + var twenum = twcap.ReadEnumerationBoxed(MemoryManager); + if (twenum.Items != null && twenum.DefaultIndex < twenum.Items.Length) + { + value.Add(twenum.Items[twenum.DefaultIndex]); + } + break; + case TWON.RANGE: + var range = twcap.ReadRangeBoxed(MemoryManager); + if (range != null) value.Add(range.DefaultValue); + break; + case TWON.ARRAY: + var twarr = twcap.ReadArrayBoxed(MemoryManager); + if (twarr != null && twarr.Count > 0) value.AddRange(twarr); + break; + default: + twcap.Free(MemoryManager); break; + } + } + return sts; + } + + /// + /// Gets a CAP's raw supported values. + /// Caller will need to manually read and free the memory. + /// + /// + /// + /// + public STS GetCapValues(CAP cap, out TW_CAPABILITY value) + { + value = new TW_CAPABILITY(cap); + if (_currentDs == null) return STS.SequenceError(); + + return WrapInSTS(DGControl.Capability.Get(_appIdentity, _currentDs, ref value)); + } + + + /// + /// Gets a CAP's supported values. This is a simplified version that doesn't require + /// manual reading, but may or may not work. + /// + /// + /// + /// + /// + public STS GetCapValues(CAP cap, out ValueContainer value) where TValue : struct + { + value = new ValueContainer { ContainerType = TWON.DONTCARE }; + var sts = GetCapValues(cap, out TW_CAPABILITY twcap); + if (sts.RC == TWRC.SUCCESS) + { + value.ContainerType = twcap.ConType; + switch (twcap.ConType) + { + case TWON.ONEVALUE: + value.OneValue = twcap.ReadOneValue(MemoryManager); + break; + case TWON.ENUMERATION: + var twenum = twcap.ReadEnumeration(MemoryManager); + if (twenum.Items != null) + { + value.EnumValue = twenum; + } + break; + case TWON.RANGE: + var range = twcap.ReadRange(MemoryManager); + value.RangeValue = range; + break; + case TWON.ARRAY: + var twarr = twcap.ReadArray(MemoryManager); + if (twarr != null) + { + value.ArrayValue = twarr; + } + break; + default: + twcap.Free(MemoryManager); break; + } + } + return sts; + } + + + /// + /// Gets a CAP's supported values. This is a simplified version that doesn't require + /// manual reading, but may or may not work. + /// + /// + /// + /// + public STS GetCapValuesBoxed(CAP cap, out ValueContainer value) + { + value = new ValueContainer { ContainerType = TWON.DONTCARE }; + var sts = GetCapValues(cap, out TW_CAPABILITY twcap); + if (sts.RC == TWRC.SUCCESS) + { + value.ContainerType = twcap.ConType; + switch (twcap.ConType) + { + case TWON.ONEVALUE: + value.OneValue = twcap.ReadOneValueBoxed(MemoryManager); + break; + case TWON.ENUMERATION: + var twenum = twcap.ReadEnumerationBoxed(MemoryManager); + if (twenum.Items != null) + { + value.EnumValue = twenum; + } + break; + case TWON.RANGE: + var range = twcap.ReadRangeBoxed(MemoryManager); + value.RangeValue = range; + break; + case TWON.ARRAY: + var twarr = twcap.ReadArrayBoxed(MemoryManager); + if (twarr != null) + { + value.ArrayValue = twarr; + } + break; + default: + twcap.Free(MemoryManager); break; + } + } + return sts; + } + + /// + /// Gets a CAP's help text (description). + /// This may not work due to unclear spec. + /// + /// + /// + /// + public STS GetCapHelp(CAP cap, out string? help) + { + help = null; + if (_currentDs == null) return STS.SequenceError(); + + var value = new TW_CAPABILITY(cap); + var rc = DGControl.Capability.GetHelp(_appIdentity, _currentDs, ref value); + if (rc == TWRC.SUCCESS) + { + help = value.ReadString(MemoryManager, false); + } + value.Free(MemoryManager); + return WrapInSTS(rc); + } + + /// + /// Gets a CAP's text name label. + /// This may not work due to unclear spec. + /// + /// + /// + /// + public STS GetCapLabel(CAP cap, out string? label) + { + label = null; + if (_currentDs == null) return STS.SequenceError(); + + var value = new TW_CAPABILITY(cap) { ConType = TWON.ONEVALUE }; + var rc = DGControl.Capability.GetLabel(_appIdentity, _currentDs, ref value); + if (rc == TWRC.SUCCESS) + { + label = value.ReadString(MemoryManager, false); + } + value.Free(MemoryManager); + return WrapInSTS(rc); + } + + /// + /// Gets a CAP's enum/array value label texts. + /// + /// + /// + /// + public STS GetCapLabelEnum(CAP cap, out IList labels) + { + labels = Array.Empty(); + if (_currentDs == null) return STS.SequenceError(); + + var value = new TW_CAPABILITY(cap); + var rc = DGControl.Capability.GetLabelEnum(_appIdentity, _currentDs, ref value); + if (rc == TWRC.SUCCESS) + { + // spec says they're utf8 + labels = value.ReadArray(MemoryManager, false).Select(t => t.Get(Encoding.UTF8)).ToList(); + } + value.Free(MemoryManager); + return WrapInSTS(rc); + } + + /// + /// Sets a CAP's current value. + /// An easy way to create a value is to use the + /// + /// extension method (or the other container variants). + /// Memory of the value will be freed afterwards. + /// + /// + /// + public STS SetCap(ref TW_CAPABILITY value) + { + if (_currentDs == null) return STS.SequenceError(); + + var rc = DGControl.Capability.Set(_appIdentity, _currentDs, ref value); + value.Free(MemoryManager); + + if (value.Cap == CAP.CAP_LANGUAGE && rc == TWRC.SUCCESS) + { + RefreshCapLanguage(); } - /// - /// Resets a CAP's current value to power-on default. - /// - /// - /// - /// - /// - public STS ResetCap(CAP cap, out List value) where TValue : struct - { - value = []; - var sts = ResetCap(cap, out TW_CAPABILITY twcap); + return WrapInSTS(rc); + } - if (sts.RC == TWRC.SUCCESS) - { - switch (twcap.ConType) - { - case TWON.ONEVALUE: - value.Add(twcap.ReadOneValue(this)); - break; - case TWON.ENUMERATION: - var twenum = twcap.ReadEnumeration(this); - if (twenum.Items != null && twenum.CurrentIndex < twenum.Items.Length) - { - value.Add(twenum.Items[twenum.CurrentIndex]); - } - break; - case TWON.RANGE: - var range = twcap.ReadRange(this); - if (range != null) value.Add(range.CurrentValue); - break; - case TWON.ARRAY: - var twarr = twcap.ReadArray(this); - if (twarr != null && twarr.Count > 0) value.AddRange(twarr); - break; - default: - twcap.Free(this); break; - } - } - return sts; + /// + /// A simpler cap value setter for one-value type. + /// + /// + /// + /// + /// + public STS SetCap(CAP cap, TValue value) where TValue : struct + { + var twcap = ValueWriter.CreateOneValueCap(cap, MemoryManager, value); + return SetCap(ref twcap); + } + + /// + /// A cap value setter for enumeration container type. + /// + /// + /// + /// + /// + public STS SetCap(CAP cap, Enumeration value) where TValue : struct + { + var twcap = ValueWriter.CreateEnumCap(cap, MemoryManager, value); + return SetCap(ref twcap); + } + + /// + /// A cap value setter for range container type. + /// + /// + /// + /// + /// + public STS SetCap(CAP cap, Range value) where TValue : struct + { + var twcap = ValueWriter.CreateRangeCap(cap, MemoryManager, value); + return SetCap(ref twcap); + } + + /// + /// A cap value setter for array container type. + /// + /// + /// + /// + /// + public STS SetCap(CAP cap, IList value) where TValue : struct + { + var twcap = ValueWriter.CreateArrayCap(cap, MemoryManager, value); + return SetCap(ref twcap); + } + + /// + /// A cap value setter for all kinds of container types. + /// + /// + /// + /// + /// + /// + public STS SetCap(CAP cap, ValueContainer value) where TValue : struct + { + switch (value.ContainerType) + { + case TWON.ONEVALUE: + return SetCap(cap, value.OneValue); + case TWON.ENUMERATION: + if (value.EnumValue == null) + throw new ArgumentException("EnumValue cannot be null when ContainerType is ENUMERATION.", nameof(value)); + return SetCap(cap, value.EnumValue); + case TWON.RANGE: + if (value.RangeValue == null) + throw new ArgumentException("RangeValue cannot be null when ContainerType is RANGE.", nameof(value)); + return SetCap(cap, value.RangeValue); + case TWON.ARRAY: + if (value.ArrayValue == null) + throw new ArgumentException("ArrayValue cannot be null when ContainerType is ARRAY.", nameof(value)); + return SetCap(cap, value.ArrayValue); + default: + throw new ArgumentException("Unsupported ContainerType for setting CAP.", nameof(value)); + } + } + + /// + /// Sets a CAP's constraint values. + /// An easy way to create a value is to use the + /// + /// extension method (or the other container variants). + /// Memory of the value will be freed afterwards. + /// + /// + /// + public STS SetConstraint(ref TW_CAPABILITY value) + { + if (_currentDs == null) return STS.SequenceError(); + + var rc = DGControl.Capability.SetConstraint(_appIdentity, _currentDs, ref value); + value.Free(MemoryManager); + return WrapInSTS(rc); + } + + + /// + /// A simpler cap constraint setter for one-value type. + /// + /// + /// + /// + /// + public STS SetConstraint(CAP cap, TValue value) where TValue : struct + { + var twcap = ValueWriter.CreateOneValueCap(cap, MemoryManager, value); + return SetConstraint(ref twcap); + } + + /// + /// A cap constraint setter for enumeration container type. + /// + /// + /// + /// + /// + public STS SetConstraint(CAP cap, Enumeration value) where TValue : struct + { + var twcap = ValueWriter.CreateEnumCap(cap, MemoryManager, value); + return SetConstraint(ref twcap); + } + + /// + /// A cap constraint setter for range container type. + /// + /// + /// + /// + /// + public STS SetConstraint(CAP cap, Range value) where TValue : struct + { + var twcap = ValueWriter.CreateRangeCap(cap, MemoryManager, value); + return SetConstraint(ref twcap); + } + + /// + /// A cap constraint setter for array container type. + /// + /// + /// + /// + /// + public STS SetConstraint(CAP cap, IList value) where TValue : struct + { + var twcap = ValueWriter.CreateArrayCap(cap, MemoryManager, value); + return SetConstraint(ref twcap); + } + + /// + /// A cap constraint setter for all kinds of container types. + /// + /// + /// + /// + /// + /// + public STS SetConstraint(CAP cap, ValueContainer value) where TValue : struct + { + switch (value.ContainerType) + { + case TWON.ONEVALUE: + return SetConstraint(cap, value.OneValue); + case TWON.ENUMERATION: + if (value.EnumValue == null) + throw new ArgumentException("EnumValue cannot be null when ContainerType is ENUMERATION.", nameof(value)); + return SetConstraint(cap, value.EnumValue); + case TWON.RANGE: + if (value.RangeValue == null) + throw new ArgumentException("RangeValue cannot be null when ContainerType is RANGE.", nameof(value)); + return SetConstraint(cap, value.RangeValue); + case TWON.ARRAY: + if (value.ArrayValue == null) + throw new ArgumentException("ArrayValue cannot be null when ContainerType is ARRAY.", nameof(value)); + return SetConstraint(cap, value.ArrayValue); + default: + throw new ArgumentException("Unsupported ContainerType for setting CAP constraint.", nameof(value)); + } + } + + /// + /// Resets a CAP's current value to power-on default. + /// Caller will need to manually read and free the memory. + /// + /// + /// + /// + public STS ResetCap(CAP cap, out TW_CAPABILITY value) + { + value = new TW_CAPABILITY(cap); + if (_currentDs == null) return STS.SequenceError(); + + var rc = DGControl.Capability.Reset(_appIdentity, _currentDs, ref value); + + if (value.Cap == CAP.CAP_LANGUAGE && rc == TWRC.SUCCESS) + { + RefreshCapLanguage(); } - /// - /// Resets a CAP's current value to power-on default. - /// - /// - /// - /// - public STS ResetCapBoxed(CAP cap, out List value) - { - value = []; - var sts = ResetCap(cap, out TW_CAPABILITY twcap); + return WrapInSTS(rc); + } - if (sts.RC == TWRC.SUCCESS) + /// + /// Resets a CAP's current value to power-on default. + /// + /// + /// + /// + /// + public STS ResetCap(CAP cap, out List value) where TValue : struct + { + value = []; + var sts = ResetCap(cap, out TW_CAPABILITY twcap); + + if (sts.RC == TWRC.SUCCESS) + { + switch (twcap.ConType) { - switch (twcap.ConType) - { - case TWON.ONEVALUE: - var read = twcap.ReadOneValueBoxed(this); - if (read != null) value.Add(read); - break; - case TWON.ENUMERATION: - var twenum = twcap.ReadEnumerationBoxed(this); - if (twenum.Items != null && twenum.CurrentIndex < twenum.Items.Length) - { - value.Add(twenum.Items[twenum.CurrentIndex]); - } - break; - case TWON.RANGE: - var range = twcap.ReadRangeBoxed(this); - if (range != null) value.Add(range.CurrentValue); - break; - case TWON.ARRAY: - var twarr = twcap.ReadArrayBoxed(this); - if (twarr != null && twarr.Count > 0) value.AddRange(twarr); - break; - default: - twcap.Free(this); break; - } + case TWON.ONEVALUE: + value.Add(twcap.ReadOneValue(MemoryManager)); + break; + case TWON.ENUMERATION: + var twenum = twcap.ReadEnumeration(MemoryManager); + if (twenum.Items != null && twenum.CurrentIndex < twenum.Items.Length) + { + value.Add(twenum.Items[twenum.CurrentIndex]); + } + break; + case TWON.RANGE: + var range = twcap.ReadRange(MemoryManager); + if (range != null) value.Add(range.CurrentValue); + break; + case TWON.ARRAY: + var twarr = twcap.ReadArray(MemoryManager); + if (twarr != null && twarr.Count > 0) value.AddRange(twarr); + break; + default: + twcap.Free(MemoryManager); break; } - return sts; + } + return sts; + } + + /// + /// Resets a CAP's current value to power-on default. + /// + /// + /// + /// + public STS ResetCapBoxed(CAP cap, out List value) + { + value = []; + var sts = ResetCap(cap, out TW_CAPABILITY twcap); + + if (sts.RC == TWRC.SUCCESS) + { + switch (twcap.ConType) + { + case TWON.ONEVALUE: + var read = twcap.ReadOneValueBoxed(MemoryManager); + if (read != null) value.Add(read); + break; + case TWON.ENUMERATION: + var twenum = twcap.ReadEnumerationBoxed(MemoryManager); + if (twenum.Items != null && twenum.CurrentIndex < twenum.Items.Length) + { + value.Add(twenum.Items[twenum.CurrentIndex]); + } + break; + case TWON.RANGE: + var range = twcap.ReadRangeBoxed(MemoryManager); + if (range != null) value.Add(range.CurrentValue); + break; + case TWON.ARRAY: + var twarr = twcap.ReadArrayBoxed(MemoryManager); + if (twarr != null && twarr.Count > 0) value.AddRange(twarr); + break; + default: + twcap.Free(MemoryManager); break; + } + } + return sts; + } + + /// + /// Resets all CAP values and constraint to power-on defaults. + /// + /// + public STS ResetAllCaps() + { + if (_currentDs == null) return STS.SequenceError(); + + // no memory is allocated for this + var value = new TW_CAPABILITY(CAP.CAP_SUPPORTEDCAPS); + var rc = DGControl.Capability.ResetAll(_appIdentity, _currentDs, ref value); + + if (rc == TWRC.SUCCESS) + { + RefreshCapLanguage(); } - /// - /// Resets all CAP values and constraint to power-on defaults. - /// - /// - public STS ResetAllCaps() + return WrapInSTS(rc); + } + + private void RefreshCapLanguage() + { + var rc2 = GetCapCurrent(CAP.CAP_LANGUAGE, out List lang); + if (rc2.RC == TWRC.SUCCESS && lang.Count > 0) { - // no memory is allocated for this - var value = new TW_CAPABILITY(CAP.CAP_SUPPORTEDCAPS); - var rc = DGControl.Capability.ResetAll(ref _appIdentity, ref _currentDS, ref value); - - if (rc == TWRC.SUCCESS) - { - RefreshCapLanguage(); - } - - return WrapInSTS(rc); - } - - private void RefreshCapLanguage() - { - var rc2 = GetCapCurrent(CAP.CAP_LANGUAGE, out List lang); - if (rc2.RC == TWRC.SUCCESS && lang.Count > 0) - { - Language.Set(lang.First()); - } + Language.Set(lang.First()); } } } diff --git a/src/NTwain/TwainAppSession.FileSystem.cs b/src/NTwain/TwainAppSession.FileSystem.cs deleted file mode 100644 index b79fa5a..0000000 --- a/src/NTwain/TwainAppSession.FileSystem.cs +++ /dev/null @@ -1,37 +0,0 @@ -using NTwain.Data; -using NTwain.Triplets; -using System.Collections.Generic; - -namespace NTwain; - -// this file contains FileSystem mgmt methods - -partial class TwainAppSession -{ - /// - /// Enumerate file system items at current level. - /// - /// - public IEnumerable GetFileSystemItems() - { - TW_FILESYSTEM fs = default; - for (var rc = DGControl.FileSystem.GetFirstFile(ref _appIdentity, ref _currentDS, ref fs); - rc == TWRC.SUCCESS; - rc = DGControl.FileSystem.GetNextFile(ref _appIdentity, ref _currentDS, ref fs)) - { - yield return fs; - } - } - - /// - /// Try to change to a different directory. - /// - /// - /// - /// - public STS ChangeFileSystemDirectory(TWFY type, string path) - { - TW_FILESYSTEM fs = new() { FileType = (int)type, InputName = path }; - return WrapInSTS(DGControl.FileSystem.ChangeDirectory(ref _appIdentity, ref _currentDS, ref fs)); - } -} diff --git a/src/NTwain/TwainAppSession.Memory.cs b/src/NTwain/TwainAppSession.Memory.cs deleted file mode 100644 index 768cd63..0000000 --- a/src/NTwain/TwainAppSession.Memory.cs +++ /dev/null @@ -1,131 +0,0 @@ -using NTwain.Data; -using System; -using System.Runtime.InteropServices; -using Windows.Win32; -using Windows.Win32.Foundation; -using Windows.Win32.System.Memory; - -namespace NTwain -{ - // this file contains memory methods - - partial class TwainAppSession : IMemoryManager - { - TW_ENTRYPOINT_DELEGATES _entryPoint; - - public IntPtr Alloc(uint size) - { - if (_entryPoint.DSM_MemAllocate != null) - { - return _entryPoint.DSM_MemAllocate(size); - } - else if (TWPlatform.IsWindows) - { -#pragma warning disable CA1416 // Validate platform compatibility - return PInvoke.GlobalAlloc(GLOBAL_ALLOC_FLAGS.GHND, size); -#pragma warning restore CA1416 // Validate platform compatibility - //return WinNativeMethods.GlobalAlloc(WinNativeMethods.AllocFlag.GHND, (UIntPtr)size); - } - else if (TWPlatform.IsLinux) - { - return Marshal.AllocHGlobal((int)size); - } - else if (TWPlatform.IsMacOSX) - { - return Marshal.AllocHGlobal((int)size); - } - else - { - throw new PlatformNotSupportedException(); - } - } - - public void Free(IntPtr handle) - { - if (handle == IntPtr.Zero) return; - - if (_entryPoint.DSM_MemFree != null) - { - _entryPoint.DSM_MemFree(handle); - } - else if (TWPlatform.IsWindows) - { -#pragma warning disable CA1416 // Validate platform compatibility - PInvoke.GlobalFree((HGLOBAL)handle); -#pragma warning restore CA1416 // Validate platform compatibility - //WinNativeMethods.GlobalFree(handle); - } - else if (TWPlatform.IsLinux) - { - Marshal.FreeHGlobal(handle); - } - else if (TWPlatform.IsMacOSX) - { - Marshal.FreeHGlobal(handle); - } - else - { - throw new PlatformNotSupportedException(); - } - } - - public IntPtr Lock(IntPtr handle) - { - if (handle == IntPtr.Zero) return IntPtr.Zero; - - if (_entryPoint.DSM_MemLock != null) - { - return _entryPoint.DSM_MemLock(handle); - } - else if (TWPlatform.IsWindows) - { - unsafe - { -#pragma warning disable CA1416 // Validate platform compatibility - return (IntPtr)PInvoke.GlobalLock((HGLOBAL)handle); -#pragma warning restore CA1416 // Validate platform compatibility - } - //return WinNativeMethods.GlobalLock(handle); - } - else if (TWPlatform.IsLinux) - { - return handle; - } - else if (TWPlatform.IsMacOSX) - { - return handle; - } - else - { - throw new PlatformNotSupportedException(); - } - } - - public void Unlock(IntPtr handle) - { - if (handle == IntPtr.Zero) return; - - if (_entryPoint.DSM_MemUnlock != null) - { - _entryPoint.DSM_MemUnlock(handle); - } - else if (TWPlatform.IsWindows) - { -#pragma warning disable CA1416 // Validate platform compatibility - PInvoke.GlobalUnlock((HGLOBAL)handle); -#pragma warning restore CA1416 // Validate platform compatibility - //WinNativeMethods.GlobalUnlock(handle); - } - else if (TWPlatform.IsLinux) - { - } - else if (TWPlatform.IsMacOSX) - { - } - else - { - throw new PlatformNotSupportedException(); - } - } - } -} diff --git a/src/NTwain/TwainAppSession.PropEvents.cs b/src/NTwain/TwainAppSession.PropEvents.cs deleted file mode 100644 index 7fe6f21..0000000 --- a/src/NTwain/TwainAppSession.PropEvents.cs +++ /dev/null @@ -1,169 +0,0 @@ -using NTwain.Data; -using NTwain.Triplets; -using System; -using System.Runtime.InteropServices; - -namespace NTwain; - -// this file contains property and event definitions - -partial class TwainAppSession -{ - /// - /// Gets the app identity. - /// - public TW_IDENTITY_LEGACY AppIdentity - { - get => _appIdentity; - } - internal TW_IDENTITY_LEGACY _appIdentity; - - /// - /// Gets the current (opened) data source. - /// - public TW_IDENTITY_LEGACY CurrentSource - { - get => _currentDS; - protected set - { - _currentDS = value; - try - { - CurrentSourceChanged?.Invoke(this, value); - } - catch { } - } - } - internal TW_IDENTITY_LEGACY _currentDS; - - /// - /// Gets/sets the default data source. - /// - public TW_IDENTITY_LEGACY DefaultSource - { - get => _defaultDS; - } - TW_IDENTITY_LEGACY _defaultDS; - - - /// - /// Current TWAIN session state. - /// - public STATE State - { - get => _state; - protected set - { - if (_state != value) - { - _state = value; - try - { - StateChanged?.Invoke(this, value); - } - catch { } - } - } - } - STATE _state = STATE.S1; - - - /// - /// Gets/sets the current source's settings as opaque data. - /// Returns null if not supported. This is only valid in . - /// - public byte[]? CustomDsData - { - get - { - var rc = DGControl.CustomDsData.Get(ref _appIdentity, ref _currentDS, out TW_CUSTOMDSDATA data); - if (rc == TWRC.SUCCESS) - { - if (data.hData != IntPtr.Zero && data.InfoLength > 0) - { - try - { - var lockedPtr = Lock(data.hData); - var bytes = new byte[data.InfoLength]; - Marshal.Copy(lockedPtr, bytes, 0, bytes.Length); - return bytes; - } - finally - { - Unlock(data.hData); - Free(data.hData); - } - } - } - return null; - } - set - { - if (value == null || value.Length == 0) return; - - TW_CUSTOMDSDATA data = default; - data.InfoLength = (uint)value.Length; - data.hData = Alloc(data.InfoLength); - try - { - var lockedPtr = Lock(data.hData); - Marshal.Copy(value, 0, lockedPtr, value.Length); - Unlock(data.hData); - var rc = DGControl.CustomDsData.Set(ref _appIdentity, ref _currentDS, ref data); - } - finally - { - // should be freed already if no error but just in case - if (data.hData != IntPtr.Zero) Free(data.hData); - } - } - } - - - /// - /// Fires when changes. - /// - public event TwainEventDelegate? StateChanged; - - /// - /// Fires when changes. - /// - public event TwainEventDelegate? DefaultSourceChanged; - - /// - /// Fires when changes (opened and closed). - /// - public event TwainEventDelegate? CurrentSourceChanged; - - /// - /// Fires when source has moved from enabled to disabled state. - /// - public event TwainEventDelegate? SourceDisabled; - - /// - /// Fires when the source has some device event happening. - /// - public event TwainEventDelegate? DeviceEvent; - - /// - /// Fires when there's an error during transfer. - /// - public event TwainEventDelegate? TransferError; - - /// - /// Fires when there's an upcoming transfer. App can inspect the image info - /// and cancel if needed. - /// - public event TwainEventDelegate? TransferReady; - - /// - /// Fires when there's a transfer cancellation, e.g. if the user pressed the "Cancel" button. - /// - public event TwainEventDelegate? TransferCanceled; - - /// - /// Fires when transferred data is available for app to use. - /// This is NOT raised on the UI thread for reasons. - /// - public event TwainEventDelegate? Transferred; -} diff --git a/src/NTwain/TwainAppSession.Sources.cs b/src/NTwain/TwainAppSession.Sources.cs deleted file mode 100644 index 0b6c277..0000000 --- a/src/NTwain/TwainAppSession.Sources.cs +++ /dev/null @@ -1,217 +0,0 @@ -using NTwain.Data; -using NTwain.Triplets; -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; - -namespace NTwain -{ - // this file contains data source utilities - - partial class TwainAppSession - { - /// - /// Gets all available sources. - /// - /// - public IEnumerable GetSources() - { - var rc = DGControl.Identity.GetFirst(ref _appIdentity, out TW_IDENTITY_LEGACY ds); - while (rc == TWRC.SUCCESS) - { - yield return ds; - rc = DGControl.Identity.GetNext(ref _appIdentity, out ds); - } - } - - /// - /// Shows the TWAIN source selection UI for setting the default source. - /// Only included for completeness, not recommended for real app usage. - /// - public STS ShowUserSelect() - { - var rc = DGControl.Identity.UserSelect(ref _appIdentity, out TW_IDENTITY_LEGACY ds); - if (rc == TWRC.SUCCESS) - { - _defaultDS = ds; - try - { - DefaultSourceChanged?.Invoke(this, ds); - } - catch { } - } - return WrapInSTS(rc); - } - - /// - /// Loads and opens the specified data source. - /// - /// - public STS OpenSource(TW_IDENTITY_LEGACY source) - { - var rc = DGControl.Identity.OpenDS(ref _appIdentity, ref source); - if (rc == TWRC.SUCCESS) - { - State = STATE.S4; - RegisterCallback(); - Language.Set(source.Version.Language); - CurrentSource = source; - } - return WrapInSTS(rc); - } - - /// - /// Closes the currently open data source. - /// - public STS CloseSource() - { - var rc = DGControl.Identity.CloseDS(ref _appIdentity, ref _currentDS); - if (rc == TWRC.SUCCESS) - { - State = STATE.S3; - CurrentSource = default; - } - return WrapInSTS(rc); - } - - /// - /// Sets the default data source. - /// - /// - /// - public STS SetDefaultSource(TW_IDENTITY_LEGACY source) - { - // this doesn't work on windows legacy twain_32.dll - - var rc = DGControl.Identity.Set(ref _appIdentity, ref source); - if (rc == TWRC.SUCCESS) - { - _defaultDS = source; - try - { - DefaultSourceChanged?.Invoke(this, source); - } - catch { } - } - return WrapInSTS(rc); - } - - - /// - /// Enables the currently open source. - /// - /// Whether to show driver interface. - /// If true try to display only driver dialog (no capture). - /// Otherwise capturing will begin after this. - /// - public STS EnableSource(bool showUI, bool uiOnly) - { - if (_pumpThreadMarshaller == null) return EnableSourceReal(showUI, uiOnly); - - var sts = default(STS); - _pumpThreadMarshaller.Send(_ => - { - sts = EnableSourceReal(showUI, uiOnly); - }, null); - return sts; - } - - private STS EnableSourceReal(bool showUI, bool uiOnly) - { - if (State > STATE.S4) - { - // already enabled :( - // TODO: should bring it down? - } - _closeDsRequested = false; - _userInterface = new TW_USERINTERFACE - { - ShowUI = (ushort)((showUI || uiOnly) ? 1 : 0), - hParent = _hwnd, - }; - var rc = uiOnly ? - DGControl.UserInterface.EnableDSUIOnly(ref _appIdentity, ref _currentDS, ref _userInterface) : - DGControl.UserInterface.EnableDS(ref _appIdentity, ref _currentDS, ref _userInterface); - if (rc == TWRC.SUCCESS || (!uiOnly && !showUI && rc == TWRC.CHECKSTATUS)) - { - State = STATE.S5; - } - else - { - _userInterface = default; - } - return WrapInSTS(rc); - } - - /// - /// Disables the currently enabled source. - /// - /// - public STS DisableSource() - { - if (_pumpThreadMarshaller == null) return DisableSourceReal(); - - var sts = default(STS); - _pumpThreadMarshaller.Send(_ => - { - sts = DisableSourceReal(); - }, null); - return sts; - } - STS DisableSourceReal() - { - _closeDsRequested = true; - var rc = DGControl.UserInterface.DisableDS(ref _appIdentity, ref _currentDS, ref _userInterface); - if (rc == TWRC.SUCCESS) - { - State = STATE.S4; - SourceDisabled?.Invoke(this, _currentDS); - } - return WrapInSTS(rc); - } - - /// - /// Reads information relating to the last capture run. - /// Only valid on state 4 after a capture. - /// - public STS GetMetrics(out TW_METRICS metrics) - { - return WrapInSTS(DGControl.Metrics.Get(ref _appIdentity, ref _currentDS, out metrics)); - } - - /// - /// Sends a TWAIN Direct task from the application to the driver. - /// - /// The TWAIN Direct task in JSON. - /// The current system being used to connect the application to the scanner. - /// - public TwainDirectTaskResult SetTwainDirectTask(string taskJson, ushort communicationManager = 0) - { - var result = new TwainDirectTaskResult { ReturnCode = TWRC.FAILURE }; - TW_TWAINDIRECT task = default; - try - { - task.SizeOf = (uint)Marshal.SizeOf(typeof(TW_TWAINDIRECT)); - task.CommunicationManager = communicationManager; - task.Send = taskJson.StringToPtrUTF8(this, out uint length); - task.SendSize = length; - - result.ReturnCode = DGControl.TwainDirect.SetTask(ref _appIdentity, ref _currentDS, ref task); - if (result.ReturnCode == TWRC.FAILURE) - { - result.Status = GetLastStatus(); - } - else if (result.ReturnCode == TWRC.SUCCESS && task.ReceiveSize > 0 && task.Receive != IntPtr.Zero) - { - result.ResponseJson = task.Receive.PtrToStringUTF8(this, (int)task.ReceiveSize); - } - } - finally - { - //if (task.Send != IntPtr.Zero) Free(task.Send); // does source free the Send? - if (task.Receive != IntPtr.Zero) Free(task.Receive); - } - return result; - } - } -} diff --git a/src/NTwain/TwainAppSession.TwainMisc.cs b/src/NTwain/TwainAppSession.TwainMisc.cs new file mode 100644 index 0000000..cace274 --- /dev/null +++ b/src/NTwain/TwainAppSession.TwainMisc.cs @@ -0,0 +1,101 @@ +using NTwain.Data; +using NTwain.Triplets; +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace NTwain; + +// this file contains wrapped twain calls that are +// complicated to use. + +partial class TwainAppSession +{ + /// + /// Gets/sets the current source's settings as opaque data. + /// Returns null if not supported. This is only valid in . + /// + public byte[]? CustomDsData + { + get + { + if (_currentDs == null) return null; + + var rc = DGControl.CustomDsData.Get(_appIdentity, _currentDs, out TW_CUSTOMDSDATA data); + if (rc == TWRC.SUCCESS) + { + if (data.hData != IntPtr.Zero && data.InfoLength > 0) + { + try + { + var lockedPtr = MemoryManager.Lock(data.hData); + var bytes = new byte[data.InfoLength]; + Marshal.Copy(lockedPtr, bytes, 0, bytes.Length); + return bytes; + } + finally + { + MemoryManager.Unlock(data.hData); + MemoryManager.Free(data.hData); + } + } + } + return null; + } + set + { + if (value == null || value.Length == 0 || _currentDs == null) return; + + TW_CUSTOMDSDATA data = default; + data.InfoLength = (uint)value.Length; + data.hData = MemoryManager.Alloc(data.InfoLength); + try + { + var lockedPtr = MemoryManager.Lock(data.hData); + Marshal.Copy(value, 0, lockedPtr, value.Length); + MemoryManager.Unlock(data.hData); + var rc = DGControl.CustomDsData.Set(_appIdentity, _currentDs, ref data); + } + finally + { + // should be freed already if no error but just in case + if (data.hData != IntPtr.Zero) MemoryManager.Free(data.hData); + } + } + } + + + /// + /// Enumerate file system items at current level. + /// + /// + public IEnumerable GetFileSystemItems() + { + if (_currentDs == null) yield break; + + TW_FILESYSTEM fs = default; + for (var rc = DGControl.FileSystem.GetFirstFile(_appIdentity, _currentDs, ref fs); + rc == TWRC.SUCCESS; + rc = DGControl.FileSystem.GetNextFile(_appIdentity, _currentDs, ref fs)) + { + yield return fs; + } + } + + /// + /// Try to change to a different directory. + /// + /// + /// + /// + public STS ChangeFileSystemDirectory(TWFY type, string path) + { + if (_currentDs == null) return STS.SequenceError(); + + return InvokeTriplet(() => + { + TW_FILESYSTEM fs = new() { FileType = (int)type, InputName = path }; + return WrapInSTS(DGControl.FileSystem.ChangeDirectory(_appIdentity, _currentDs, ref fs)); + }); + } +} diff --git a/src/NTwain/TwainAppSession.TwainState.cs b/src/NTwain/TwainAppSession.TwainState.cs new file mode 100644 index 0000000..5841ca2 --- /dev/null +++ b/src/NTwain/TwainAppSession.TwainState.cs @@ -0,0 +1,570 @@ +using NTwain.Data; +using NTwain.Events; +using NTwain.Platform; +using NTwain.Triplets; +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Threading; + +// this file tracks twain state and has methods that can change the twain state and +// manage data sources. + +namespace NTwain; + +partial class TwainAppSession +{ + /// + /// Occurs when the changes. + /// + public event EventHandler? StateChanged; + + /// + /// Occurs when the changes. + /// + public event EventHandler? CurrentSourceChanged; + + /// + /// Fires when changes. + /// + public event EventHandler? DefaultSourceChanged; + + /// + /// Fires when the source is disabled. + /// + public event EventHandler? SourceDisabled; + + /// + /// Fires when the source sends a device event. + /// + public event EventHandler? DeviceEvent; + + /// + /// Fires when there's an upcoming transfer. App can inspect the image info, + /// setup certain transfer parameters, or cancel the transfer if needed. + /// + public event EventHandler? TransferReady; + + /// + /// Fires when there's an error during transfer. + /// + public event EventHandler? TransferError; + + /// + /// Fires when transferred data is available for app to use. + /// + public event EventHandler? Transferred; + + internal void RaiseTransferError(TransferErrorEventArgs args) + { + RaiseEvent(TransferError, args); + } + internal void RaiseTransferReady(TransferReadyEventArgs args) + { + RaiseEventAndWait(TransferReady, args); + } + internal void RaiseTransferred(TransferredEventArgs args) + { + // no wait here, app can handle at its leisure + RaiseEvent(Transferred, args); + } + + + + private STATE _state; + /// + /// The current TWAIN state of the application session. + /// + public STATE State + { + get { return _state; } + internal set + { + _state = value; + RaiseEvent(StateChanged, value); + } + } + + + TWIdentityWrapper? _defaultDs; + /// + /// The default TWAIN data source. + /// + public TWIdentityWrapper? DefaultSource + { + get { return _defaultDs; } + private set + { + _defaultDs = value; + RaiseEvent(DefaultSourceChanged, value); + } + } + + + TWIdentityWrapper? _currentDs; + /// + /// The current open TWAIN data source. + /// + public TWIdentityWrapper? CurrentSource + { + get { return _currentDs; } + private set + { + _currentDs = value; + RaiseEvent(CurrentSourceChanged, value); + } + } + + private IMemoryManager? _memoryManager; + + /// + /// Gets the memory manager for this TWAIN session. + /// + /// If OpenDsm() has not been called. + public IMemoryManager MemoryManager + { + get + { + if (_memoryManager == null) + { + throw new InvalidOperationException("Memory manager is not initialized. Call OpenDsm() first."); + } + return _memoryManager; + } + } + + /// + /// Raises an event on the application thread context if available, otherwise on the current thread. + /// + /// The type of event arguments. + /// The event handler to invoke. + /// The event arguments. + protected void RaiseEvent(EventHandler? eventHandler, TEventArgs eventArgs) + { + if (eventHandler == null) return; + + if (AppThreadContext != null) + { + AppThreadContext.Post(_ => eventHandler(this, eventArgs), null); + } + else + { + eventHandler(this, eventArgs); + } + } + + /// + /// Raises an event on the application thread context if available, otherwise on the current thread. + /// + /// The type of event arguments. + /// The event handler to invoke. + /// The event arguments. + protected void RaiseEventAndWait(EventHandler? eventHandler, TEventArgs eventArgs) + { + if (eventHandler == null) return; + + if (AppThreadContext != null) + { + using var waitHandle = new ManualResetEventSlim(false); + AppThreadContext.Post(_ => + { + try + { + eventHandler(this, eventArgs); + } + finally + { + waitHandle.Set(); + } + }, null); + waitHandle.Wait(); + } + else + { + eventHandler(this, eventArgs); + } + } + + /// + /// Executes a triplet call, handling Windows-specific synchronization if needed. + /// + /// The return type of the triplet call. + /// The triplet action to execute. + /// The result of the triplet call. + protected T InvokeTriplet(Func action) + { + if (OperatingSystem.IsWindowsVersionAtLeast(5, 1, 2600) && _twainPumpForWin != null) + { + T result = default!; + _twainPumpForWin.SynchronizationContext!.Send(obj => + { + result = action(); + }, this); + return result; + } + else + { + return action(); + } + } + + /// + /// Loads and opens the DSM for use. Can only be called in S1 or S3 state. + /// + /// + public STS OpenDsm() + { + if (State >= STATE.S3) + return new STS { RC = TWRC.FAILURE, STATUS = new TW_STATUS { ConditionCode = TWCC.SEQERROR } }; + + var hwnd = OperatingSystem.IsWindowsVersionAtLeast(5, 1, 2600) && _twainPumpForWin != null + ? _twainPumpForWin.MainWindow + : IntPtr.Zero; + + var sts = InvokeTriplet(() => + { + var rc = DGControl.Parent.OpenDSM(_appIdentity, hwnd); + var sts = WrapInSTS(rc, forDsm: true); + + if (rc == TWRC.SUCCESS) + { + State = STATE.S3; + + // determine memory mgmt routines used + TW_ENTRYPOINT_DELEGATES entryPoint = default; + if (((DG)_appIdentity.SupportedGroups & DG.DSM2) == DG.DSM2) + { + DGControl.EntryPoint.Get(_appIdentity, out entryPoint); + } + + if (entryPoint.HasDelegates()) + { + _memoryManager = new TwainMemoryManager(entryPoint); + } + else if (OperatingSystem.IsWindowsVersionAtLeast(5, 1, 2600)) + { + _memoryManager = new Win32MemoryManager(); + } + else + { + _memoryManager = new FallbackMemoryManager(); + } + + // get default source + if (DGControl.Identity.GetDefault(_appIdentity, out TWIdentityWrapper ds) == TWRC.SUCCESS) + { + DefaultSource = ds; + } + } + return sts; + }); + + return sts; + } + + /// + /// Closes the DSM. Can only be done in S3 state. + /// + /// + public STS CloseDsm() + { + if (State != STATE.S3) + return new STS { RC = TWRC.FAILURE, STATUS = new TW_STATUS { ConditionCode = TWCC.SEQERROR } }; + + var hwnd = OperatingSystem.IsWindowsVersionAtLeast(5, 1, 2600) && _twainPumpForWin != null + ? _twainPumpForWin.MainWindow + : IntPtr.Zero; + + var sts = InvokeTriplet(() => + { + var rc = DGControl.Parent.CloseDSM(_appIdentity, hwnd); + if (rc == TWRC.SUCCESS) + { + _memoryManager = null; + DefaultSource = null; + State = STATE.S2; + } + return WrapInSTS(rc, forDsm: true); + }); + return sts; + } + + /// + /// Gets all available sources. + /// + /// + public IList GetSources() + { + // haven't found a way to enumerate like before with + // potentially a different thread so List it is. + return InvokeTriplet(() => + { + List sources = []; + var rc = DGControl.Identity.GetFirst(_appIdentity, out TWIdentityWrapper ds); + while (rc == TWRC.SUCCESS) + { + sources.Add(ds); + rc = DGControl.Identity.GetNext(_appIdentity, out ds); + } + return sources; + }); + } + + /// + /// Shows the TWAIN source selection UI for setting the default source. + /// Only included for completeness, not recommended for real app usage. + /// + public STS ShowUserSelect() + { + return InvokeTriplet(() => + { + var rc = DGControl.Identity.UserSelect(_appIdentity, out TWIdentityWrapper ds); + if (rc == TWRC.SUCCESS) + { + DefaultSource = ds; + } + return WrapInSTS(rc); + }); + } + + /// + /// Sets the default data source. + /// + /// + /// + public STS SetDefaultSource(TWIdentityWrapper source) + { + // this doesn't work on windows legacy twain_32.dll + + return InvokeTriplet(() => + { + var rc = DGControl.Identity.Set(_appIdentity, source); + if (rc == TWRC.SUCCESS) + { + DefaultSource = source; + } + return WrapInSTS(rc); + }); + } + + /// + /// Opens the specified source. + /// + /// + /// + public STS OpenSource(TWIdentityWrapper source) + { + if (_currentDs != null) + { + var sts = CloseSource(); + if (!sts.IsSuccess) return sts; + } + + return InvokeTriplet(() => + { + var rc = DGControl.Identity.OpenDS(_appIdentity, source); + if (rc == TWRC.SUCCESS) + { + Language.Set(source.Version.Language); + CurrentSource = source; + RegisterCallback(); + State = STATE.S4; + } + return WrapInSTS(rc); + }); + } + + /// + /// Closes the current source if it's open. + /// + /// + public STS CloseSource() + { + if (_currentDs == null) + { + return STS.SequenceError(); + } + + return InvokeTriplet(() => + { + var rc = DGControl.Identity.CloseDS(_appIdentity, _currentDs); + if (rc == TWRC.SUCCESS) + { + CurrentSource = null; + State = STATE.S3; + } + return WrapInSTS(rc); + }); + } + + /// + /// Option that was used to enable the current data source. + /// + public SourceEnableOption EnabledWithOption { get; private set; } + + /// + /// Enables the current data source, optionally displaying the user interface based on the specified option. + /// + /// + public STS EnableSource(SourceEnableOption option) + { + if (_currentDs == null) + { + return STS.SequenceError(); + } + + var hwnd = OperatingSystem.IsWindowsVersionAtLeast(5, 1, 2600) && _twainPumpForWin != null + ? _twainPumpForWin.MainWindow + : IntPtr.Zero; + + return InvokeTriplet(() => + { + var showUI = option == SourceEnableOption.ShowUI || option == SourceEnableOption.UIOnly; + + TW_USERINTERFACE ui = new() + { + ShowUI = (ushort)(showUI ? 1 : 0), + hParent = hwnd + }; + + _transferThread.NotifyTransferReady(false); + + var rc = option == SourceEnableOption.UIOnly ? + DGControl.UserInterface.EnableDSUIOnly(_appIdentity, _currentDs, ref ui) : + DGControl.UserInterface.EnableDS(_appIdentity, _currentDs, ref ui); + + // user may choose no ui but if it's not supported by source + // then it returns check status but still considered a success. + if (rc == TWRC.SUCCESS || (!showUI && rc == TWRC.CHECKSTATUS)) + { + _transferThread.CloseDsRequested = false; + EnabledWithOption = option; + State = STATE.S5; + } + return WrapInSTS(rc); + }); + } + + + /// + /// Disables the currently enabled source. + /// + /// + public STS DisableSource() + { + if (_currentDs == null) + { + return STS.SequenceError(); + } + + var hwnd = OperatingSystem.IsWindowsVersionAtLeast(5, 1, 2600) && _twainPumpForWin != null + ? _twainPumpForWin.MainWindow + : IntPtr.Zero; + + return InvokeTriplet(() => + { + var showUI = EnabledWithOption == SourceEnableOption.ShowUI || EnabledWithOption == SourceEnableOption.UIOnly; + TW_USERINTERFACE ui = new() + { + ShowUI = (ushort)(showUI ? 1 : 0), + hParent = hwnd + }; + + var rc = DGControl.UserInterface.DisableDS(_appIdentity, _currentDs, ref ui); + if (rc == TWRC.SUCCESS) + { + State = STATE.S4; + RaiseEvent(SourceDisabled, _currentDs); + } + return WrapInSTS(rc); + }); + } + + /// + /// Wraps a return code with additional status if not successful. + /// Use this right after an API call to get its condition code. + /// + /// + /// true to get status for dsm operation error, false to get status for ds operation error, + /// + public STS WrapInSTS(TWRC rc, bool forDsm = false) + { + if (rc != TWRC.FAILURE) return new STS { RC = rc }; + var sts = new STS { RC = rc, STATUS = GetLastStatus(forDsm) }; + + if (sts.STATUS.ConditionCode == TWCC.BADDEST) + { + // TODO: the current ds is bad, should assume we're back in S3? + // needs the dest parameter to find out. + } + else if (sts.STATUS.ConditionCode == TWCC.BUMMER) + { + // TODO: notify with critical event to end the twain stuff + } + return sts; + } + + /// + /// Gets the last status code if an operation did not return success. + /// This can only be done once after an error. + /// + /// true to get status for dsm operation error, false to get status for ds operation error, + /// + public TW_STATUS GetLastStatus(bool forDsm = false) + { + return InvokeTriplet(() => + { + TW_STATUS status = default; + if (forDsm) + { + DGControl.Status.GetForDSM(_appIdentity, out status); + } + else + { + if (_currentDs == null) return new TW_STATUS { ConditionCode = TWCC.BADDEST }; + DGControl.Status.GetForDS(_appIdentity, _currentDs, out status); + } + return status; + }); + } + + + /// + /// Tries to bring the TWAIN session down to some state. + /// For use when things got out of hand. + /// + /// + /// The final state. + public STATE TryStepdown(STATE targetState) + { + return InvokeTriplet(() => + { + if (targetState < State && State >= STATE.S6) + { + var pending = TW_PENDINGXFERS.DONTCARE(); + DGControl.PendingXfers.EndXfer(_appIdentity, _currentDs!, ref pending); + pending = TW_PENDINGXFERS.DONTCARE(); + DGControl.PendingXfers.Reset(_appIdentity, _currentDs!, ref pending); + } + + if (targetState < State && State == STATE.S5) + { + DisableSource(); + } + + if (targetState < State && State == STATE.S4) + { + CloseSource(); + } + + if (targetState < State && State == STATE.S3) + { + CloseDsm(); + } + + // can't go lower than S2 + + return State; + }); + } +} diff --git a/src/NTwain/TwainAppSession.Windows.cs b/src/NTwain/TwainAppSession.Windows.cs deleted file mode 100644 index 7fc270a..0000000 --- a/src/NTwain/TwainAppSession.Windows.cs +++ /dev/null @@ -1,116 +0,0 @@ -#if WINDOWS || NETFRAMEWORK -using Microsoft.Extensions.Logging; -using NTwain.Data; -using NTwain.Native; -using NTwain.Triplets; -using System; -using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Windows.Forms; -using System.Windows.Interop; -using Windows.Win32.Foundation; -using MSG = NTwain.Data.MSG; - -namespace NTwain -{ - - // contains parts for winform/wpf message loop integration - - partial class TwainAppSession : IMessageFilter - { - HwndSource? _wpfhook; - - /// - /// Registers this session for use in a Winform UI thread. - /// - public void AddWinformFilter() - { - Application.AddMessageFilter(this); - } - /// - /// Unregisters this session if previously registered with . - /// - public void RemoveWinformFilter() - { - Application.RemoveMessageFilter(this); - } - - /// - /// Registers this session for use in a WPF UI thread. - /// This requires the hwnd used in - /// be a valid WPF window handle. - /// - public void AddWpfHook() - { - if (_wpfhook == null) - { - _wpfhook = HwndSource.FromHwnd(_hwnd); - _wpfhook.AddHook(WpfHook); - } - } - /// - /// Unregisters this session if previously registered with . - /// - public void RemoveWpfHook() - { - if (_wpfhook != null) - { - _wpfhook.RemoveHook(WpfHook); - _wpfhook = null; - } - } - - bool IMessageFilter.PreFilterMessage(ref Message m) - { - return WndProc(m.HWnd, m.Msg, m.WParam, m.LParam); - } - - IntPtr WpfHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) - { - handled = WndProc(hwnd, msg, wParam, lParam); - return IntPtr.Zero; - } - - /// - /// Method to check window message and handle it if it's for the TWAIN source.' - /// - /// - /// - /// - /// - /// - public bool WndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam) - { - // this handles the message from a typical WndProc message loop and checks if it's for the TWAIN source. - bool handled = false; - if (_state >= STATE.S5) - { - Windows.Win32.UI.WindowsAndMessaging.MSG winMsg = new() - { - hwnd = (HWND)hWnd, - message = (uint)msg, - wParam = TWPlatform.Is32bit ? new UIntPtr((uint)wParam.ToInt32()) : new UIntPtr((ulong)wParam.ToInt64()), - lParam = lParam - }; - // no need to do another lock call when using marshal alloc - if (_procEvent.pEvent == IntPtr.Zero) - _procEvent.pEvent = Marshal.AllocHGlobal(Marshal.SizeOf(winMsg)); - Marshal.StructureToPtr(winMsg, _procEvent.pEvent, true); - - if (!_closeDsRequested) - { - var rc = DGControl.Event.ProcessEvent(ref _appIdentity, ref _currentDS, ref _procEvent); - handled = rc == TWRC.DSEVENT; - if (_procEvent.TWMessage != 0 && (handled || rc == TWRC.NOTDSEVENT)) - { - //Logger.LogTrace("[thread {ThreadId}] CheckIfTwainMessage at state {State} with MSG={Msg}.", - // Environment.CurrentManagedThreadId, State, _procEvent.TWMessage); - HandleSourceMsg((MSG)_procEvent.TWMessage); - } - } - } - return handled; - } - } -} -#endif \ No newline at end of file diff --git a/src/NTwain/TwainAppSession.Xfers.cs b/src/NTwain/TwainAppSession.Xfers.cs deleted file mode 100644 index ecf73ff..0000000 --- a/src/NTwain/TwainAppSession.Xfers.cs +++ /dev/null @@ -1,602 +0,0 @@ -using Microsoft.Extensions.Logging; -using NTwain.Data; -using NTwain.Native; -using NTwain.Triplets; -using System; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices; -using System.Threading; - -namespace NTwain -{ - // this file contains various xfer methods - - partial class TwainAppSession - { - /// - /// Can only be called in state 7, so it's hidden here and - /// only exposed in data transferred event. - /// - /// - /// - internal STS GetExtendedImageInfo(ref TW_EXTIMAGEINFO container) - { - return WrapInSTS(DGImage.ExtImageInfo.Get(ref _appIdentity, ref _currentDS, ref container)); - } - /// - /// Kodak use. - /// - /// - /// - internal STS GetExtendedImageInfoSpecial(ref TW_EXTIMAGEINFO container) - { - return WrapInSTS(DGImage.ExtImageInfo.GetSpecial(ref _appIdentity, ref _currentDS, ref container)); - } - - /// - /// Can only be called in state 6, so it's here and only exposed - /// in transfer ready event. - /// - /// - /// - internal STS SetFileXfer(ref TW_SETUPFILEXFER settings) - { - return WrapInSTS(DGControl.SetupFileXfer.Set(ref _appIdentity, ref _currentDS, ref settings)); - } - - - /// - /// Start the transfer loop. - /// This should be called after receiving - /// in the background thread. - /// - void EnterTransferRoutine() - { - // TODO: currently implemented routine doesn't quite work for audio as described in spec - - - // default options if source doesn't support changing them or whatever - bool xferImage = true; - bool xferAudio = false; - if (DGControl.XferGroup.Get(ref _appIdentity, ref _currentDS, out DG xferType) == TWRC.SUCCESS) - { - xferAudio = (xferType & DG.AUDIO) == DG.AUDIO; - var dsName = _currentDS.ProductName.ToString(); - // check for Plustek OpticSlim 2680H, this scanner returns wrong xferGroup after first scanning - if (dsName.IndexOf("Plustek", StringComparison.OrdinalIgnoreCase) > -1 && - dsName.IndexOf("OpticSlim", StringComparison.OrdinalIgnoreCase) > -1 && - dsName.IndexOf("2680H", StringComparison.OrdinalIgnoreCase) > -1) - { - xferImage = true; - } - else - { - // some DS end up getting none but we will assume it's image - xferImage = xferType == 0 || (xferType & DG.IMAGE) == DG.IMAGE; - } - } - - var imgXferMech = TWSX.NATIVE; - var audXferMech = TWSX.NATIVE; - if (xferImage) imgXferMech = Caps.ICAP_XFERMECH.GetCurrent().FirstOrDefault(); - else if (xferAudio) audXferMech = Caps.ACAP_XFERMECH.GetCurrent().FirstOrDefault(); - - TW_PENDINGXFERS pending = TW_PENDINGXFERS.DONTCARE(); - var sts = WrapInSTS(DGControl.PendingXfers.Get(ref _appIdentity, ref _currentDS, ref pending)); - if (sts.RC == TWRC.SUCCESS) - { - do - { - var readyArgs = new TransferReadyEventArgs(this, imgXferMech, audXferMech, pending.Count, (TWEJ)pending.EOJ); - try - { - TransferReady?.Invoke(this, readyArgs); - } - catch { } // don't let consumer kill the loop if they have exception - - if (readyArgs.Cancel == CancelType.EndNow || _closeDsRequested) - { - // TODO: need to call EndXfer first? - pending = TW_PENDINGXFERS.DONTCARE(); - sts = WrapInSTS(DGControl.PendingXfers.Reset(ref _appIdentity, ref _currentDS, ref pending)); - if (sts.RC == TWRC.SUCCESS && xferImage) State = STATE.S5; - } - else if (readyArgs.Cancel == CancelType.SkipCurrent) - { - pending = TW_PENDINGXFERS.DONTCARE(); - sts = WrapInSTS(DGControl.PendingXfers.EndXfer(ref _appIdentity, ref _currentDS, ref pending)); - if (sts.RC == TWRC.SUCCESS) - { - if (xferImage) - { - State = pending.Count == 0 ? STATE.S5 : STATE.S6; - } - else if (xferAudio) - { - State = STATE.S6; - } - } - } - else - { - if (readyArgs.Cancel == CancelType.Graceful) - { - // ignore rc in this and continue transfer as normal - pending = TW_PENDINGXFERS.DONTCARE(); - DGControl.PendingXfers.StopFeeder(ref _appIdentity, ref _currentDS, ref pending); - } - - try - { - if (readyArgs.Cancel != CancelType.SkipCurrent) - { - // transfer normally and only if someone's listening - // to DataTransferred event - if (xferImage) - { - switch (imgXferMech) - { - case TWSX.NATIVE: - sts = TransferNativeImage(ref pending); - break; - case TWSX.FILE: - sts = TransferFileImage(ref pending); - break; - case TWSX.MEMORY: - sts = TransferMemoryImage(ref pending); - break; - case TWSX.MEMFILE: - sts = TransferMemoryFileImage(ref pending); - break; - } - } - else if (xferAudio) - { - switch (audXferMech) - { - case TWSX.NATIVE: - sts = TransferNativeAudio(ref pending); - break; - case TWSX.FILE: - sts = TransferFileAudio(ref pending); - break; - } - } - HandleXferCode(ref sts, ref pending, isEnd: false); - } - } - catch (Exception ex) - { - try - { - TransferError?.Invoke(this, new TransferErrorEventArgs(ex)); - } - catch { } - } - } - } while (sts.RC == TWRC.SUCCESS && pending.Count != 0); - } - - HandleXferCode(ref sts, ref pending, isEnd: true); - - if (State >= STATE.S5) - { - DisableSource(); - } - _inTransfer = false; - } - - private void HandleXferCode(ref STS sts, ref TW_PENDINGXFERS pending, bool isEnd) - { - switch (sts.RC) - { - case TWRC.SUCCESS: - case TWRC.XFERDONE: - // ok to keep going - if (isEnd) - { - //DGControl.PendingXfers.EndXfer(ref _appIdentity, ref _currentDS, ref pending); - } - break; - case TWRC.CANCEL: - // might eventually have option to cancel this or all like transfer ready - try - { - TransferCanceled?.Invoke(this, new TransferCanceledEventArgs()); - } - catch { } - pending = TW_PENDINGXFERS.DONTCARE(); - sts = WrapInSTS(DGControl.PendingXfers.EndXfer(ref _appIdentity, ref _currentDS, ref pending)); - pending = TW_PENDINGXFERS.DONTCARE(); - sts = WrapInSTS(DGControl.PendingXfers.Reset(ref _appIdentity, ref _currentDS, ref pending)); - if (sts.RC == TWRC.SUCCESS) State = STATE.S5; - break; - default: - // TODO: raise error event - switch (sts.STATUS.ConditionCode) - { - case TWCC.SEQERROR: - if (isEnd) - { - // special break down to state 5 - pending = TW_PENDINGXFERS.DONTCARE(); - sts = WrapInSTS(DGControl.PendingXfers.EndXfer(ref _appIdentity, ref _currentDS, ref pending)); - State = STATE.S6; - pending = TW_PENDINGXFERS.DONTCARE(); - sts = WrapInSTS(DGControl.PendingXfers.Reset(ref _appIdentity, ref _currentDS, ref pending)); - State = STATE.S5; - } - break; - case TWCC.DAMAGEDCORNER: - case TWCC.DOCTOODARK: - case TWCC.DOCTOOLIGHT: - case TWCC.FOCUSERROR: - case TWCC.NOMEDIA: - case TWCC.PAPERDOUBLEFEED: - case TWCC.PAPERJAM: - pending = TW_PENDINGXFERS.DONTCARE(); - sts = WrapInSTS(DGControl.PendingXfers.EndXfer(ref _appIdentity, ref _currentDS, ref pending)); - break; - case TWCC.OPERATIONERROR: - var indicators = Caps.CAP_INDICATORS.GetCurrent().FirstOrDefault(); - if (_userInterface.ShowUI == 0 && indicators == TW_BOOL.False) - { - // todo: alert user and drop to S4 - pending = TW_PENDINGXFERS.DONTCARE(); - sts = WrapInSTS(DGControl.PendingXfers.EndXfer(ref _appIdentity, ref _currentDS, ref pending)); - pending = TW_PENDINGXFERS.DONTCARE(); - sts = WrapInSTS(DGControl.PendingXfers.Reset(ref _appIdentity, ref _currentDS, ref pending)); - } - break; - } - break; - } - } - - private STS TransferFileAudio(ref TW_PENDINGXFERS pending) - { - // assuming user already configured the transfer in transferready event, - // get what will be transferred - var rc = DGControl.SetupFileXfer.Get(ref _appIdentity, ref _currentDS, out TW_SETUPFILEXFER fileSetup); - if (rc != TWRC.SUCCESS) return WrapInSTS(rc); - - // and just start it - var sts = WrapInSTS(DGAudio.AudioFileXfer.Get(ref _appIdentity, ref _currentDS)); - - if (sts.RC == TWRC.XFERDONE) - { - State = STATE.S7; - try - { - DGAudio.AudioInfo.Get(ref _appIdentity, ref _currentDS, out TW_AUDIOINFO info); - var args = new TransferredEventArgs(info, fileSetup); - Transferred?.Invoke(this, args); - } - catch { } - - pending = TW_PENDINGXFERS.DONTCARE(); - sts = WrapInSTS(DGControl.PendingXfers.EndXfer(ref _appIdentity, ref _currentDS, ref pending)); - if (sts.RC == TWRC.SUCCESS) - { - State = STATE.S6; - } - } - return sts; - } - - private STS TransferNativeAudio(ref TW_PENDINGXFERS pending) - { - IntPtr dataPtr = IntPtr.Zero; - IntPtr lockedPtr = IntPtr.Zero; - try - { - var sts = WrapInSTS(DGAudio.AudioNativeXfer.Get(ref _appIdentity, ref _currentDS, out dataPtr)); - if (sts.RC == TWRC.XFERDONE) - { - State = STATE.S7; - lockedPtr = Lock(dataPtr); - BufferedData? data = default; - - // TODO: don't know how to read wav/aiff from pointer yet - - if (data != null) - { - try - { - DGAudio.AudioInfo.Get(ref _appIdentity, ref _currentDS, out TW_AUDIOINFO info); - var args = new TransferredEventArgs(info, data); - Transferred?.Invoke(this, args); - } - catch - { - data.Dispose(); - } - } - } - - pending = TW_PENDINGXFERS.DONTCARE(); - sts = WrapInSTS(DGControl.PendingXfers.EndXfer(ref _appIdentity, ref _currentDS, ref pending)); - if (sts.RC == TWRC.SUCCESS) - { - State = STATE.S6; - } - return sts; - } - finally - { - if (lockedPtr != IntPtr.Zero) Unlock(dataPtr); - if (dataPtr != IntPtr.Zero) Free(dataPtr); - } - } - - private STS TransferMemoryImage(ref TW_PENDINGXFERS pending) - { - var rc = DGControl.SetupMemXfer.Get(ref _appIdentity, ref _currentDS, out TW_SETUPMEMXFER memSetup); - if (rc != TWRC.SUCCESS) return WrapInSTS(rc); - rc = DGImage.ImageInfo.Get(ref _appIdentity, ref _currentDS, out TW_IMAGEINFO info); - if (rc != TWRC.SUCCESS) return WrapInSTS(rc); - rc = DGImage.ImageLayout.Get(ref _appIdentity, ref _currentDS, out TW_IMAGELAYOUT layout); - if (rc != TWRC.SUCCESS) return WrapInSTS(rc); - - uint buffSize = memSetup.DetermineBufferSize(); - var memPtr = Alloc(buffSize); - - TW_IMAGEMEMXFER memXfer = TW_IMAGEMEMXFER.DONTCARE(); - TW_IMAGEMEMXFER_MACOSX memXferOSX = TW_IMAGEMEMXFER_MACOSX.DONTCARE(); - memXfer.Memory = new TW_MEMORY - { - Flags = (uint)(TWMF.APPOWNS | TWMF.POINTER), - Length = buffSize, - TheMem = memPtr - }; - memXferOSX.Memory = memXfer.Memory; - - byte[] dotnetBuff = BufferedData.MemPool.Rent((int)buffSize); - try - { - do - { - rc = TWPlatform.IsMacOSX ? - DGImage.ImageMemXfer.Get(ref _appIdentity, ref _currentDS, ref memXferOSX) : - DGImage.ImageMemXfer.Get(ref _appIdentity, ref _currentDS, ref memXfer); - - if (rc == TWRC.SUCCESS || rc == TWRC.XFERDONE) - { - try - { - var written = TWPlatform.IsMacOSX ? - memXferOSX.BytesWritten : memXfer.BytesWritten; - - IntPtr lockedPtr = Lock(memPtr); - - // assemble! - - //Marshal.Copy(lockedPtr, dotnetBuff, 0, (int)written); - //outStream.Write(dotnetBuff, 0, (int)written); - } - finally - { - Unlock(memPtr); - } - } - } while (rc == TWRC.SUCCESS); - } - finally - { - if (memPtr != IntPtr.Zero) Free(memPtr); - BufferedData.MemPool.Return(dotnetBuff); - } - - - if (rc == TWRC.XFERDONE) - { - try - { - DGImage.ImageInfo.Get(ref _appIdentity, ref _currentDS, out info); - //var args = new DataTransferredEventArgs(info, null, outStream.ToArray()); - //DataTransferred?.Invoke(this, args); - } - catch { } - - pending = TW_PENDINGXFERS.DONTCARE(); - var sts = WrapInSTS(DGControl.PendingXfers.EndXfer(ref _appIdentity, ref _currentDS, ref pending)); - if (sts.RC == TWRC.SUCCESS) - { - State = pending.Count == 0 ? STATE.S5 : STATE.S6; - } - return sts; - } - return WrapInSTS(rc); - } - - private STS TransferMemoryFileImage(ref TW_PENDINGXFERS pending) - { - var rc = DGControl.SetupFileXfer.Get(ref _appIdentity, ref _currentDS, out TW_SETUPFILEXFER fileSetup); - if (rc != TWRC.SUCCESS) return WrapInSTS(rc); - rc = DGControl.SetupMemXfer.Get(ref _appIdentity, ref _currentDS, out TW_SETUPMEMXFER memSetup); - if (rc != TWRC.SUCCESS) return WrapInSTS(rc); - - uint buffSize = memSetup.DetermineBufferSize(); - var memPtr = Alloc(buffSize); - - TW_IMAGEMEMXFER memXfer = TW_IMAGEMEMXFER.DONTCARE(); - TW_IMAGEMEMXFER_MACOSX memXferOSX = TW_IMAGEMEMXFER_MACOSX.DONTCARE(); - memXfer.Memory = new TW_MEMORY - { - Flags = (uint)(TWMF.APPOWNS | TWMF.POINTER), - Length = buffSize, - TheMem = memPtr - }; - memXferOSX.Memory = memXfer.Memory; - - // TODO: how to get actual file size before hand? Is it imagelayout? - // otherwise will just write to stream with lots of copies - byte[] dotnetBuff = BufferedData.MemPool.Rent((int)buffSize); - using var outStream = new MemoryStream(); - try - { - do - { - rc = TWPlatform.IsMacOSX ? - DGImage.ImageMemFileXfer.Get(ref _appIdentity, ref _currentDS, ref memXferOSX) : - DGImage.ImageMemFileXfer.Get(ref _appIdentity, ref _currentDS, ref memXfer); - - if (rc == TWRC.SUCCESS || rc == TWRC.XFERDONE) - { - try - { - var written = TWPlatform.IsMacOSX ? - memXferOSX.BytesWritten : memXfer.BytesWritten; - - IntPtr lockedPtr = Lock(memPtr); - Marshal.Copy(lockedPtr, dotnetBuff, 0, (int)written); - outStream.Write(dotnetBuff, 0, (int)written); - } - finally - { - Unlock(memPtr); - } - } - } while (rc == TWRC.SUCCESS); - } - finally - { - if (memPtr != IntPtr.Zero) Free(memPtr); - BufferedData.MemPool.Return(dotnetBuff); - } - - if (rc == TWRC.XFERDONE) - { - try - { - DGImage.ImageInfo.Get(ref _appIdentity, ref _currentDS, out TW_IMAGEINFO info); - // ToArray bypasses the XferMemPool but I guess this will have to do for now - var args = new TransferredEventArgs(this, info, fileSetup, new BufferedData(outStream.ToArray(), (int)outStream.Length, false)); - Transferred?.Invoke(this, args); - } - catch { } - - pending = TW_PENDINGXFERS.DONTCARE(); - var sts = WrapInSTS(DGControl.PendingXfers.EndXfer(ref _appIdentity, ref _currentDS, ref pending)); - if (sts.RC == TWRC.SUCCESS) - { - State = pending.Count == 0 ? STATE.S5 : STATE.S6; - } - return sts; - } - return WrapInSTS(rc); - } - - private STS TransferFileImage(ref TW_PENDINGXFERS pending) - { - // assuming user already configured the transfer in transferready event, - // get what will be transferred - DGControl.SetupFileXfer.Get(ref _appIdentity, ref _currentDS, out TW_SETUPFILEXFER fileSetup); - // and just start it - - int tries = 0; - RETRY: - var sts = WrapInSTS(DGImage.ImageFileXfer.Get(ref _appIdentity, ref _currentDS)); - - if (sts.RC == TWRC.XFERDONE) - { - State = STATE.S7; - try - { - DGImage.ImageInfo.Get(ref _appIdentity, ref _currentDS, out TW_IMAGEINFO info); - var args = new TransferredEventArgs(this, info, fileSetup, default); - Transferred?.Invoke(this, args); - } - catch { } - - pending = TW_PENDINGXFERS.DONTCARE(); - sts = WrapInSTS(DGControl.PendingXfers.EndXfer(ref _appIdentity, ref _currentDS, ref pending)); - if (sts.RC == TWRC.SUCCESS) - { - State = pending.Count == 0 ? STATE.S5 : STATE.S6; - } - } - else - { - // sometimes it errors only due to timing so wait a bit and try again - if (sts.RC == TWRC.FAILURE && (sts.ConditionCode == TWCC.None || sts.ConditionCode == TWCC.SEQERROR)) - { - if (tries++ < 3) - { - Logger.LogDebug("Using fileXfer timing workaround try {Tries}.", tries); - Thread.Sleep(500); - goto RETRY; - } - } - else - { - Debugger.Break(); - } - } - return sts; - } - - private STS TransferNativeImage(ref TW_PENDINGXFERS pending) - { - IntPtr dataPtr = IntPtr.Zero; - IntPtr lockedPtr = IntPtr.Zero; - try - { - DGImage.ImageInfo.Get(ref _appIdentity, ref _currentDS, out TW_IMAGEINFO info); - var sts = WrapInSTS(DGImage.ImageNativeXfer.Get(ref _appIdentity, ref _currentDS, out dataPtr)); - if (sts.RC == TWRC.XFERDONE) - { - State = STATE.S7; - lockedPtr = Lock(dataPtr); - BufferedData? data = default; - - if (ImageTools.IsDib(lockedPtr)) - { - data = ImageTools.GetBitmapData(lockedPtr); - } - else if (ImageTools.IsTiff(lockedPtr)) - { - data = ImageTools.GetTiffData(lockedPtr); - } - else - { - // PicHandle? - // don't support more formats :( - } - - if (data != null) - { - try - { - // some sources do not support getting image info in state 7 so - // it's up there in the beginning now. - var args = new TransferredEventArgs(this, info, null, data); - Transferred?.Invoke(this, args); - } - catch - { - data.Dispose(); - } - } - - - pending = TW_PENDINGXFERS.DONTCARE(); - sts = WrapInSTS(DGControl.PendingXfers.EndXfer(ref _appIdentity, ref _currentDS, ref pending)); - if (sts.RC == TWRC.SUCCESS) - { - State = pending.Count == 0 ? STATE.S5 : STATE.S6; - } - } - return sts; - } - finally - { - if (lockedPtr != IntPtr.Zero) Unlock(dataPtr); - if (dataPtr != IntPtr.Zero) Free(dataPtr); - } - } - - } -} diff --git a/src/NTwain/TwainAppSession.cs b/src/NTwain/TwainAppSession.cs index b2ed147..014c591 100644 --- a/src/NTwain/TwainAppSession.cs +++ b/src/NTwain/TwainAppSession.cs @@ -1,366 +1,165 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using NTwain.Data; -using NTwain.Triplets; +using NTwain.Platform; using System; -using System.IO.Packaging; using System.Reflection; using System.Runtime.InteropServices; using System.Text; using System.Threading; -using System.Threading.Tasks; +using WinMSG = Windows.Win32.UI.WindowsAndMessaging.MSG; -namespace NTwain +namespace NTwain; + +// this file is for (non-twain) setup and cleanup. + +/// +/// The main TWAIN access object for an application. +/// There should only be one of these per application. +/// +public partial class TwainAppSession : IDisposable { - // this file contains initialization/cleanup things. + // internal pump is used for windows so it can run headless + Win32MessagePump? _twainPumpForWin; + TW_EVENT _procEvent; + // transfer has to happen on its own thread (not app thread, not windows message pump thread) + // so it won't block either. + TransferLoopThread _transferThread; - public partial class TwainAppSession : IDisposable + readonly TWIdentityWrapper _appIdentity; + public TWIdentityWrapper AppIdentity { get { return _appIdentity; } } + + + /// + /// Initializes a new instance of the TwainAppSession class, configuring the application session for TWAIN + /// operations and background processing. + /// + /// The app information to use in TWAIN dsm calls. + /// If null, a default identity will be generated. + /// The synchronization context associated with the application's main thread. + /// If null, then callbacks could happen on random threads. + /// The logger instance used for diagnostic and error logging. + public TwainAppSession( + TWIdentityWrapper? appIdentity = null, + SynchronizationContext? appThreadContext = null, + ILogger? logger = null) { - /// - /// Creates TWAIN session with current app info. - /// - /// - public TwainAppSession(ILogger? logger = null) - : this(new TW_IDENTITY_LEGACY(Environment.GetCommandLineArgs()[0]), logger) { } - - /// - /// Creates TWAIN session with explicit app info. - /// - /// - /// - public TwainAppSession(TW_IDENTITY_LEGACY appId, ILogger? logger = null) - { - if (logger != null) _logger = logger; - -#if WINDOWS || NETFRAMEWORK - DSM.DsmLoader.TryLoadCustomDSM(Logger); + _appIdentity = appIdentity ?? + new TWIdentityWrapper( +#if !NETFRAMEWORK + Environment.ProcessPath ?? #endif - _appIdentity = appId; + Assembly.GetEntryAssembly()?.Location ?? + Assembly.GetExecutingAssembly().Location); - _legacyCallbackDelegate = LegacyCallbackHandler; - _osxCallbackDelegate = OSXCallbackHandler; - - StartTransferThread(); - } - - private ILogger _logger = NullLogger.Instance; - - public ILogger Logger - { - get { return _logger; } - set { _logger = value ?? NullLogger.Instance; } - } - - internal IntPtr _hwnd; - internal TW_USERINTERFACE _userInterface; // kept around for disable to use -#if WINDOWS || NETFRAMEWORK - MessagePumpThread? _selfPump; - TW_EVENT _procEvent; // kept here so the alloc/free only happens once +#if !NETFRAMEWORK + Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); #endif - // test threads a bit - //readonly BlockingCollection _bgPendingMsgs = new(); - SynchronizationContext? _pumpThreadMarshaller; - bool _closeDsRequested; - bool _inTransfer; - readonly AutoResetEvent _xferReady = new(false); - private bool disposedValue; - bool _transferInCallbackThread = true; - - void StartTransferThread() + AppThreadContext = appThreadContext ?? SynchronizationContext.Current; + _logger = logger ?? NullLogger.Instance; + _legacyCallbackDelegate = LegacyCallbackHandler; + _osxCallbackDelegate = OSXCallbackHandler; + //_dsmCalls = Channel.CreateUnbounded(); + if (OperatingSystem.IsWindowsVersionAtLeast(6, 0, 6000)) { - Thread t = new(TransferLoopLoop) - { - IsBackground = true - }; -#if WINDOWS || NETFRAMEWORK - t.SetApartmentState(ApartmentState.STA); // just in case -#endif - t.Start(); - } + DllPath.TryUseLocalDsm(); - private void TransferLoopLoop(object? obj) - { - while (!disposedValue) + // no need to do another lock call when using marshal alloc + TW_EVENT _procEvent = default; + _procEvent.pEvent = Marshal.AllocHGlobal(Marshal.SizeOf()); + + Thread pumpThread = new(() => { - try + if (OperatingSystem.IsWindowsVersionAtLeast(5, 1, 2600)) { - _xferReady.WaitOne(); - } - catch (ObjectDisposedException) { break; } - try - { - EnterTransferRoutine(); - } - catch { } - } - } - - protected virtual void Dispose(bool disposing) - { - if (!disposedValue) - { - if (disposing) - { - // this will end the bg thread - _xferReady.Dispose(); - //_bgPendingMsgs.CompleteAdding(); - } -#if WINDOWS || NETFRAMEWORK - if (_procEvent.pEvent != IntPtr.Zero) Marshal.FreeHGlobal(_procEvent.pEvent); -#endif - disposedValue = true; - } - } - - // // TODO: override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources - // ~TwainSession() - // { - // // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method - // Dispose(disposing: false); - // } - - public void Dispose() - { - // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method - Dispose(disposing: true); - GC.SuppressFinalize(this); - } - -#if WINDOWS || NETFRAMEWORK - /// - /// Loads and opens the TWAIN data source manager in a self-hosted message queue thread. - /// Must close with - /// if used. - /// - /// - public async Task OpenDSMAsync() - { - if (_selfPump == null) - { - _transferInCallbackThread = true; - var pump = new MessagePumpThread(); - var sts = await pump.AttachAsync(this); - if (sts.IsSuccess) - { - _selfPump = pump; - } - return sts; - } - return new STS { RC = TWRC.FAILURE, STATUS = new TW_STATUS { ConditionCode = TWCC.SEQERROR } }; - } - - /// - /// Closes the TWAIN data source manager if opened with . - /// - /// - /// - public async Task CloseDSMAsync() - { - if (_selfPump == null) throw new InvalidOperationException($"Cannot close if not opened with {nameof(OpenDSMAsync)}()."); - - var sts = await _selfPump.DetachAsync(); - if (sts.IsSuccess) - { - _selfPump = null; - } - return sts; - } -#endif - - /// - /// Loads and opens the TWAIN data source manager. - /// - /// Required if on Windows. - /// Context for TWAIN to invoke certain actions on the thread that the hwnd lives on. - /// - public STS OpenDSM(IntPtr hwnd, SynchronizationContext uiThreadMarshaller) - { - var rc = DGControl.Parent.OpenDSM(ref _appIdentity, hwnd); - if (rc == TWRC.SUCCESS) - { - _transferInCallbackThread = true; - _hwnd = hwnd; - _pumpThreadMarshaller = uiThreadMarshaller; - State = STATE.S3; - // get default source - if (DGControl.Identity.GetDefault(ref _appIdentity, out TW_IDENTITY_LEGACY ds) == TWRC.SUCCESS) - { - _defaultDS = ds; - try + _twainPumpForWin = new Win32MessagePump(_logger); + _twainPumpForWin.UnhandledException += (s, e) => { - DefaultSourceChanged?.Invoke(this, _defaultDS); - } - catch { } + _logger.LogError(e.Exception, "Unhandled exception in TWAIN message pump."); + e.Handled = true; + }; + _twainPumpForWin.AddMessageFilter(this); + _twainPumpForWin.Run(); } + }); + pumpThread.IsBackground = true; + pumpThread.SetApartmentState(ApartmentState.STA); + pumpThread.Start(); - // determine memory mgmt routines used - if (((DG)AppIdentity.SupportedGroups & DG.DSM2) == DG.DSM2) + while (_twainPumpForWin == null || _twainPumpForWin.MainWindow.IsNull) + { + Thread.Sleep(100); + } + } + _transferThread = new TransferLoopThread(this); + } + + + /// + /// Used to marshal results back to the application thread if set, + /// as many TWAIN activities occur on other threads. + /// + public SynchronizationContext? AppThreadContext { get; set; } + + private ILogger _logger; + + /// + /// Gets or sets the logger used to record diagnostic and operational messages for this instance. + /// + public ILogger Logger + { + get { return _logger; } + set { _logger = value ?? NullLogger.Instance; } + } + + private bool _disposed; + /// + /// Overrides to clean up resources. + /// + /// + protected virtual void OnDispose(bool disposing) + { + if (!_disposed) + { + _disposed = true; + + if (disposing) + { + _transferThread.Dispose(); + + //_dsmCalls.Writer.TryComplete(); + if (_twainPumpForWin != null && OperatingSystem.IsWindowsVersionAtLeast(5, 1, 2600)) { - DGControl.EntryPoint.Get(ref _appIdentity, out _entryPoint); + _twainPumpForWin.RemoveMessageFilter(this); + _twainPumpForWin.Quit(); + _twainPumpForWin.Dispose(); } - } - return WrapInSTS(rc, true); - } - - /// - /// Closes the TWAIN data source manager. - /// - /// - /// - public STS CloseDSM() - { -#if WINDOWS || NETFRAMEWORK - if (_selfPump != null) throw new InvalidOperationException($"Cannot close if opened with {nameof(OpenDSMAsync)}()."); -#endif - return CloseDSMReal(); - } - - /// - /// Closes the TWAIN data source manager. - /// - /// - internal STS CloseDSMReal() - { - var rc = DGControl.Parent.CloseDSM(ref _appIdentity, _hwnd); - if (rc == TWRC.SUCCESS) - { - State = STATE.S2; - _entryPoint = default; - _defaultDS = default; - try + if (_procEvent.pEvent != IntPtr.Zero) { - DefaultSourceChanged?.Invoke(this, _defaultDS); - } - catch { } - _hwnd = IntPtr.Zero; - _pumpThreadMarshaller = null; - } - return WrapInSTS(rc, true); - } - - /// - /// Wraps a return code with additional status if not successful. - /// Use this right after an API call to get its condition code. - /// - /// - /// true to get status for dsm operation error, false to get status for ds operation error, - /// - public STS WrapInSTS(TWRC rc, bool dsmOnly = false) - { - if (rc != TWRC.FAILURE) return new STS { RC = rc }; - var sts = new STS { RC = rc, STATUS = GetLastStatus(dsmOnly) }; - if (sts.STATUS.ConditionCode == TWCC.BADDEST) - { - // TODO: the current ds is bad, should assume we're back in S3? - // needs the dest parameter to find out. - } - else if (sts.STATUS.ConditionCode == TWCC.BUMMER) - { - // TODO: notify with critical event to end the twain stuff - } - return sts; - } - - /// - /// Gets the last status code if an operation did not return success. - /// This can only be done once after an error. - /// - /// true to get status for dsm operation error, false to get status for ds operation error, - /// - public TW_STATUS GetLastStatus(bool dsmOnly = false) - { - if (dsmOnly) - { - DGControl.Status.GetForDSM(ref _appIdentity, out TW_STATUS status); - return status; - } - else - { - DGControl.Status.GetForDS(ref _appIdentity, ref _currentDS, out TW_STATUS status); - return status; - } - } - - /// - /// Tries to get string representation of a previously gotten status - /// from if possible. - /// - /// - /// - public string? GetStatusText(TW_STATUS status) - { - if (DGControl.StatusUtf8.Get(ref _appIdentity, status, out TW_STATUSUTF8 extendedStatus) == TWRC.SUCCESS) - { - return extendedStatus.Read(this); - } - return null; - } - - /// - /// Tries to bring the TWAIN session down to some state. - /// - /// - /// The final state. - public STATE TryStepdown(STATE targetState) - { - int tries = 0; - while (State > targetState) - { - var oldState = State; - - switch (oldState) - { - // todo: finish - case STATE.S7: - var pending = TW_PENDINGXFERS.DONTCARE(); - DGControl.PendingXfers.EndXfer(ref _appIdentity, ref _currentDS, ref pending); - _state = STATE.S6; - break; - case STATE.S6: - pending = TW_PENDINGXFERS.DONTCARE(); - DGControl.PendingXfers.Reset(ref _appIdentity, ref _currentDS, ref pending); - _state = STATE.S5; - break; - case STATE.S5: - DisableSource(); - break; - case STATE.S4: - CloseSource(); - break; - case STATE.S3: -#if WINDOWS || NETFRAMEWORK - if (_selfPump != null) - { - try - { - _ = CloseDSMAsync(); - } - catch (InvalidOperationException) { } - } - else - { - CloseDSM(); - } -#else - CloseDSM(); -#endif - break; - case STATE.S2: - // can't really go lower - if (targetState < STATE.S2) - { - return State; - } - break; - } - if (oldState == State) - { - // didn't work - if (tries++ > 5) break; + Marshal.FreeHGlobal(_procEvent.pEvent); + _procEvent.pEvent = IntPtr.Zero; } } - return State; } } + + // // TODO: override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources + // ~TwainAppSession() + // { + // // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + // Dispose(disposing: false); + // } + + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + OnDispose(disposing: true); + GC.SuppressFinalize(this); + } + + public override string ToString() + { + return $"State: {State}, App: {_appIdentity}, Source: {_currentDs}"; + } } diff --git a/src/NTwain/TwainEventDelegate.cs b/src/NTwain/TwainEventDelegate.cs deleted file mode 100644 index 9a565bd..0000000 --- a/src/NTwain/TwainEventDelegate.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace NTwain -{ - /// - /// General event delegate use by . - /// Better than basic object sender and requires EventArgs. - /// - /// - /// - /// - public delegate void TwainEventDelegate(TwainAppSession sender, TEventArgs e); -}