diff --git a/src/NTwain/CapWrapper.cs b/src/NTwain/CapWrapper.cs index 54633b4..a0fcad9 100644 --- a/src/NTwain/CapWrapper.cs +++ b/src/NTwain/CapWrapper.cs @@ -39,7 +39,7 @@ namespace NTwain var sts = _twain.DatCapability(DG.CONTROL, MSG.QUERYSUPPORT, ref twCap); if (sts == STS.SUCCESS && twCap.ConType == TWON.ONEVALUE) { - return ValueReader.ReadOneValue(_twain, twCap); + return ValueReader.ReadOneValueContainer(_twain, ref twCap); } return TWQC.Uknown; } @@ -61,13 +61,13 @@ namespace NTwain switch (twCap.ConType) { case TWON.ONEVALUE: - return new[] { ValueReader.ReadOneValue(_twain, twCap) }; + return new[] { ValueReader.ReadOneValueContainer(_twain, ref twCap) }; case TWON.ENUMERATION: - return ValueReader.ReadEnumeration(_twain, twCap).Items; + return ValueReader.ReadEnumerationContainer(_twain, ref twCap).Items; case TWON.ARRAY: - return ValueReader.ReadArray(_twain, twCap); + return ValueReader.ReadArrayContainer(_twain, ref twCap); case TWON.RANGE: - return ValueReader.ReadRange(_twain, twCap).ToList(); + return ValueReader.ReadRangeContainer(_twain, ref twCap).ToList(); } } return EmptyArray.Value; @@ -90,14 +90,14 @@ namespace NTwain switch (twCap.ConType) { case TWON.ONEVALUE: - return ValueReader.ReadOneValue(_twain, twCap); + return ValueReader.ReadOneValueContainer(_twain, ref twCap); case TWON.ENUMERATION: - var enumeration = ValueReader.ReadEnumeration(_twain, twCap); + var enumeration = ValueReader.ReadEnumerationContainer(_twain, ref twCap); if (enumeration.CurrentIndex < enumeration.Items.Length) return enumeration.Items[enumeration.CurrentIndex]; break; case TWON.RANGE: - return ValueReader.ReadRange(_twain, twCap).CurrentValue; + return ValueReader.ReadRangeContainer(_twain, ref twCap).CurrentValue; } } return default; @@ -120,14 +120,14 @@ namespace NTwain switch (twCap.ConType) { case TWON.ONEVALUE: - return ValueReader.ReadOneValue(_twain, twCap); + return ValueReader.ReadOneValueContainer(_twain, ref twCap); case TWON.ENUMERATION: - var enumeration = ValueReader.ReadEnumeration(_twain, twCap); + var enumeration = ValueReader.ReadEnumerationContainer(_twain, ref twCap); if (enumeration.DefaultIndex < enumeration.Items.Length) return enumeration.Items[enumeration.DefaultIndex]; break; case TWON.RANGE: - return ValueReader.ReadRange(_twain, twCap).DefaultValue; + return ValueReader.ReadRangeContainer(_twain, ref twCap).DefaultValue; } } return default; @@ -147,7 +147,7 @@ namespace NTwain var sts = _twain.DatCapability(DG.CONTROL, MSG.GETLABEL, ref twCap); if (sts == STS.SUCCESS) { - return ValueReader.ReadOneString(_twain, twCap); + return ValueReader.ReadOneValueContainerString(_twain, twCap); } return null; } @@ -166,7 +166,7 @@ namespace NTwain var sts = _twain.DatCapability(DG.CONTROL, MSG.GETHELP, ref twCap); if (sts == STS.SUCCESS) { - return ValueReader.ReadOneString(_twain, twCap); + return ValueReader.ReadOneValueContainerString(_twain, twCap); } return null; } @@ -204,7 +204,7 @@ namespace NTwain }; try { - ValueWriter.WriteOneValue(_twain, ref twCap, value); + ValueWriter.WriteOneValueContainer(_twain, ref twCap, value); return _twain.DatCapability(DG.CONTROL, setMsg, ref twCap); } finally @@ -233,7 +233,7 @@ namespace NTwain }; try { - ValueWriter.WriteArray(_twain, ref twCap, values); + ValueWriter.WriteArrayContainer(_twain, ref twCap, values); return _twain.DatCapability(DG.CONTROL, setMsg, ref twCap); } finally @@ -262,7 +262,7 @@ namespace NTwain }; try { - ValueWriter.WriteRange(_twain, ref twCap, value); + ValueWriter.WriteRangeContainer(_twain, ref twCap, value); return _twain.DatCapability(DG.CONTROL, setMsg, ref twCap); } finally @@ -291,7 +291,7 @@ namespace NTwain }; try { - ValueWriter.WriteEnum(_twain, ref twCap, value); + ValueWriter.WriteEnumContainer(_twain, ref twCap, value); return _twain.DatCapability(DG.CONTROL, setMsg, ref twCap); } finally diff --git a/src/NTwain/ValueReader.cs b/src/NTwain/ValueReader.cs index 131a799..b44d7e8 100644 --- a/src/NTwain/ValueReader.cs +++ b/src/NTwain/ValueReader.cs @@ -16,7 +16,7 @@ namespace NTwain { // most of these are modified from the original TWAIN.CapabilityToCsv() - public static TValue ReadOneValue(TWAIN twain, TW_CAPABILITY cap, bool freeMemory = true) where TValue : struct + public static TValue ReadOneValueContainer(TWAIN twain, ref TW_CAPABILITY cap, bool freeMemory = true) where TValue : struct { if (cap.hContainer == IntPtr.Zero) return default; @@ -49,7 +49,7 @@ namespace NTwain if (freeMemory) twain.DsmMemFree(ref cap.hContainer); } } - public static Enumeration ReadEnumeration(TWAIN twain, TW_CAPABILITY cap, bool freeMemory = true) where TValue : struct + public static Enumeration ReadEnumerationContainer(TWAIN twain, ref TW_CAPABILITY cap, bool freeMemory = true) where TValue : struct { Enumeration retVal = new Enumeration(); @@ -117,7 +117,7 @@ namespace NTwain } return retVal; } - public static IList ReadArray(TWAIN twain, TW_CAPABILITY cap, bool freeMemory = true) where TValue : struct + public static IList ReadArrayContainer(TWAIN twain, ref TW_CAPABILITY cap, bool freeMemory = true) where TValue : struct { if (cap.hContainer == IntPtr.Zero) return EmptyArray.Value; @@ -159,7 +159,7 @@ namespace NTwain if (freeMemory) twain.DsmMemFree(ref cap.hContainer); } } - public static Range ReadRange(TWAIN twain, TW_CAPABILITY cap, bool freeMemory = true) where TValue : struct + public static Range ReadRangeContainer(TWAIN twain, ref TW_CAPABILITY cap, bool freeMemory = true) where TValue : struct { var retVal = new Range(); @@ -260,7 +260,7 @@ namespace NTwain /// /// /// - public static string ReadOneString(TWAIN twain, TW_CAPABILITY cap, bool freeMemory = true) + public static string ReadOneValueContainerString(TWAIN twain, TW_CAPABILITY cap, bool freeMemory = true) { if (cap.hContainer == IntPtr.Zero) return null; diff --git a/src/NTwain/ValueWriter.cs b/src/NTwain/ValueWriter.cs index 51414f3..a07fe1c 100644 --- a/src/NTwain/ValueWriter.cs +++ b/src/NTwain/ValueWriter.cs @@ -13,21 +13,26 @@ namespace NTwain /// public static class ValueWriter { + // most of these are modified from the original TWAIN.CsvToCapability() - public static void WriteOneValue(TWAIN twain, ref TW_CAPABILITY twCap, TValue value) where TValue : struct + public static void WriteOneValueContainer(TWAIN twain, ref TW_CAPABILITY twCap, TValue value) where TValue : struct { IntPtr lockedPtr = IntPtr.Zero; try { + if (twCap.hContainer != IntPtr.Zero) twain.DsmMemFree(ref twCap.hContainer); + TWTY itemType = GetItemType(); + + // Allocate the container (go for worst case, which is TW_STR255)... if (PlatformTools.GetPlatform() == Platform.MACOSX) { twCap.hContainer = twain.DsmMemAlloc((uint)(Marshal.SizeOf(default(TW_ONEVALUE_MACOSX)) + Marshal.SizeOf(default(TW_STR255)))); lockedPtr = twain.DsmMemLock(twCap.hContainer); - TW_ONEVALUE_MACOSX twonevaluemacosx = default(TW_ONEVALUE_MACOSX); + TW_ONEVALUE_MACOSX twonevaluemacosx = default; twonevaluemacosx.ItemType = (uint)itemType; - Marshal.StructureToPtr(twonevaluemacosx, lockedPtr, true); + Marshal.StructureToPtr(twonevaluemacosx, lockedPtr, false); lockedPtr += Marshal.SizeOf(twonevaluemacosx); } @@ -36,9 +41,9 @@ namespace NTwain twCap.hContainer = twain.DsmMemAlloc((uint)(Marshal.SizeOf(default(TW_ONEVALUE)) + Marshal.SizeOf(default(TW_STR255)))); lockedPtr = twain.DsmMemLock(twCap.hContainer); - TW_ONEVALUE twonevalue = default(TW_ONEVALUE); + TW_ONEVALUE twonevalue = default; twonevalue.ItemType = itemType; - Marshal.StructureToPtr(twonevalue, lockedPtr, true); + Marshal.StructureToPtr(twonevalue, lockedPtr, false); lockedPtr += Marshal.SizeOf(twonevalue); } @@ -51,18 +56,183 @@ namespace NTwain } } - public static void WriteArray(TWAIN twain, ref TW_CAPABILITY twCap, TValue[] values) where TValue : struct + public static void WriteArrayContainer(TWAIN twain, ref TW_CAPABILITY twCap, TValue[] values) where TValue : struct { - throw new NotImplementedException(); + IntPtr lockedPtr = IntPtr.Zero; + try + { + if (twCap.hContainer != IntPtr.Zero) twain.DsmMemFree(ref twCap.hContainer); + + TWTY itemType = GetItemType(); + + // Allocate the container (go for worst case, which is TW_STR255)... + if (PlatformTools.GetPlatform() == Platform.MACOSX) + { + // Allocate... + twCap.hContainer = twain.DsmMemAlloc((uint)(Marshal.SizeOf(default(TW_ARRAY_MACOSX)) + ((values.Length + 1) * Marshal.SizeOf(default(TW_STR255))))); + lockedPtr = twain.DsmMemLock(twCap.hContainer); + + // Set the meta data... + TW_ARRAY_MACOSX twarraymacosx = default; + twarraymacosx.ItemType = (uint)itemType; + twarraymacosx.NumItems = (uint)values.Length; + Marshal.StructureToPtr(twarraymacosx, lockedPtr, false); + + // Get the pointer to the ItemList... + lockedPtr += Marshal.SizeOf(twarraymacosx); + } + else + { + // Allocate... + twCap.hContainer = twain.DsmMemAlloc((uint)(Marshal.SizeOf(default(TW_ARRAY)) + ((values.Length + 1) * Marshal.SizeOf(default(TW_STR255))))); + lockedPtr = twain.DsmMemLock(twCap.hContainer); + + // Set the meta data... + TW_ARRAY twarray = default; + twarray.ItemType = itemType; + twarray.NumItems = (uint)values.Length; + Marshal.StructureToPtr(twarray, lockedPtr, false); + + // Get the pointer to the ItemList... + lockedPtr += Marshal.SizeOf(twarray); + } + + // Set the ItemList... + for (var i = 0; i < values.Length; i++) + { + WriteContainerData(lockedPtr, itemType, values[i], i); + } + } + finally + { + if (lockedPtr != IntPtr.Zero) twain.DsmMemUnlock(twCap.hContainer); + } } - public static void WriteRange(TWAIN twain, ref TW_CAPABILITY twCap, Range value) where TValue : struct + public static void WriteRangeContainer(TWAIN twain, ref TW_CAPABILITY twCap, Range value) where TValue : struct + { + IntPtr lockedPtr = IntPtr.Zero; + try + { + if (twCap.hContainer != IntPtr.Zero) twain.DsmMemFree(ref twCap.hContainer); + + TWTY itemType = GetItemType(); + var platform = PlatformTools.GetPlatform(); + + // Allocate the container (go for worst case, which is TW_STR255)... + if (platform == Platform.MACOSX) + { + // Allocate... + twCap.hContainer = twain.DsmMemAlloc((uint)(Marshal.SizeOf(default(TW_RANGE_MACOSX)))); + lockedPtr = twain.DsmMemLock(twCap.hContainer); + } + // Windows or the 2.4+ Linux DSM... + else if ((platform == Platform.WINDOWS) || + (twain.m_linuxdsm == TWAIN.LinuxDsm.IsLatestDsm) || + ((twain.m_blFoundLatestDsm || twain.m_blFoundLatestDsm64) && (twain.m_linuxdsm == TWAIN.LinuxDsm.IsLatestDsm))) + { + // Allocate... + twCap.hContainer = twain.DsmMemAlloc((uint)(Marshal.SizeOf(default(TW_RANGE)))); + lockedPtr = twain.DsmMemLock(twCap.hContainer); + } + // The -2.3 Linux DSM... + else + { + // Allocate... + twCap.hContainer = twain.DsmMemAlloc((uint)(Marshal.SizeOf(default(TW_RANGE_LINUX64)))); + lockedPtr = twain.DsmMemLock(twCap.hContainer); + } + + // Set the Item... + WriteRangeValues(lockedPtr, itemType, value); + } + finally + { + if (lockedPtr != IntPtr.Zero) twain.DsmMemUnlock(twCap.hContainer); + } + } + + private static void WriteRangeValues(IntPtr lockedPtr, TWTY itemType, Range value) where TValue : struct { throw new NotImplementedException(); } - public static void WriteEnum(TWAIN twain, ref TW_CAPABILITY twCap, Enumeration value) where TValue : struct + public static void WriteEnumContainer(TWAIN twain, ref TW_CAPABILITY twCap, Enumeration value) where TValue : struct { - throw new NotImplementedException(); + IntPtr lockedPtr = IntPtr.Zero; + try + { + if (twCap.hContainer != IntPtr.Zero) twain.DsmMemFree(ref twCap.hContainer); + + TWTY itemType = GetItemType(); + var platform = PlatformTools.GetPlatform(); + + // Allocate the container (go for worst case, which is TW_STR255)... + if (platform == Platform.MACOSX) + { + // Allocate... + twCap.hContainer = twain.DsmMemAlloc((uint)(Marshal.SizeOf(default(TW_ENUMERATION_MACOSX)) + ((value.Items.Length + 1) * Marshal.SizeOf(default(TW_STR255))))); + lockedPtr = twain.DsmMemLock(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); + } + // Windows or the 2.4+ Linux DSM... + else if ((platform == Platform.WINDOWS) || + (twain.m_linuxdsm == TWAIN.LinuxDsm.IsLatestDsm) || + ((twain.m_blFoundLatestDsm || twain.m_blFoundLatestDsm64) && (twain.m_linuxdsm == TWAIN.LinuxDsm.IsLatestDsm))) + { + // Allocate... + twCap.hContainer = twain.DsmMemAlloc((uint)(Marshal.SizeOf(default(TW_ENUMERATION)) + ((value.Items.Length + 1) * Marshal.SizeOf(default(TW_STR255))))); + lockedPtr = twain.DsmMemLock(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 = twain.DsmMemAlloc((uint)(Marshal.SizeOf(default(TW_ENUMERATION_LINUX64)) + ((value.Items.Length + 1) * Marshal.SizeOf(default(TW_STR255))))); + lockedPtr = twain.DsmMemLock(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); + } + } + finally + { + if (lockedPtr != IntPtr.Zero) twain.DsmMemUnlock(twCap.hContainer); + } } @@ -133,9 +303,12 @@ namespace NTwain 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(value, intptr, false); + Marshal.StructureToPtr(Convert.ToUInt32(value), intptr, false); break; case TWTY.FIX32: intptr += 4 * itemIndex;