diff --git a/src/NTwain/Data/ValueReader.cs b/src/NTwain/Data/ValueReader.cs index b4fb2dd..c5a1703 100644 --- a/src/NTwain/Data/ValueReader.cs +++ b/src/NTwain/Data/ValueReader.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.IO; using System.Runtime.InteropServices; using System.Text; @@ -9,7 +10,7 @@ namespace NTwain.Data /// /// Contains methods for reading pointers into various things. /// - public static class ValueReader + static class ValueReader { /// /// Reads pointer as UTF8 string. @@ -312,76 +313,84 @@ namespace NTwain.Data } } - ///// - ///// Read the one value of a cap as string. Only STR* and HANDLE types are supported. - ///// - ///// - ///// - ///// - ///// - //public static string ReadOneValueContainerString(IMemoryManager memMgr, TW_CAPABILITY cap, bool freeMemory = true) - //{ - // if (cap.hContainer == IntPtr.Zero) return null; + /// + /// 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); + 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 (TwainPlatform.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; + } - // try - // { - // if (cap.ConType == TWON.ONEVALUE) - // { - // TWTY itemType; - // // Mac has a level of indirection and a different structure (ick)... - // if (TwainPlatform.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: - // // 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(ref cap.hContainer); - // } - // return null; - //} /// /// Read the container pointer content. /// diff --git a/src/NTwain/TwainAppSession.Caps.cs b/src/NTwain/TwainAppSession.Caps.cs index 789ea38..0bb6227 100644 --- a/src/NTwain/TwainAppSession.Caps.cs +++ b/src/NTwain/TwainAppSession.Caps.cs @@ -171,7 +171,7 @@ namespace NTwain /// /// /// - /// + /// /// public STS GetCapValues(CAP cap, out IList values) where TValue : struct { @@ -208,7 +208,7 @@ namespace NTwain /// /// Gets a CAP's help text (description). - /// This is not implemented due to unclear spec. + /// This may not work due to unclear spec. /// /// /// @@ -220,8 +220,7 @@ namespace NTwain var rc = DGControl.Capability.GetHelp(ref _appIdentity, ref _currentDS, ref value); if (rc == TWRC.SUCCESS) { - // TODO: how to determine the length of this thing??? - var data = value.ReadOneValue(this, false); + help = value.ReadString(this, false); } value.Free(this); return WrapInSTS(rc); @@ -229,7 +228,7 @@ namespace NTwain /// /// Gets a CAP's text name label. - /// This is not implemented due to unclear spec. + /// This may not work due to unclear spec. /// /// /// @@ -241,8 +240,7 @@ namespace NTwain var rc = DGControl.Capability.GetLabel(ref _appIdentity, ref _currentDS, ref value); if (rc == TWRC.SUCCESS) { - // TODO: how to determine the length of this thing??? - var data = value.ReadOneValue(this, false); + label = value.ReadString(this, false); } value.Free(this); return WrapInSTS(rc);