public static extern ReturnCode DsmWin32( [In, Out] TW_IDENTITY origin, [In, Out] TW_IDENTITY destination, DataGroups dg, DataArgumentType dat, Message msg, ref TW_CAPABILITY data);
/// <summary> /// Generates a <see cref="TW_CAPABILITY"/> for use in capability negotiation /// using TWAIN's enum value. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="cap"></param> /// <param name="value"></param> /// <returns></returns> public TW_CAPABILITY Generate <T>(CapabilityId cap, EnumValue <T> value) { var twCap = new TW_CAPABILITY { Capability = cap, ContainerType = ContainerType.Enum, hContainer = config.MemoryManager.Allocate((uint)Marshal.SizeOf(typeof(TW_ENUMERATION))) }; if (twCap.hContainer != IntPtr.Zero) { var listSz = value.Type.GetSize() * value.ItemList.Length; TW_ENUMERATION container = new TW_ENUMERATION { ItemType = (ushort)value.Type, NumItems = (uint)value.ItemList.Length, CurrentIndex = (uint)value.CurrentIndex, DefaultIndex = (uint)value.DefaultIndex, ItemList = config.MemoryManager.Allocate((uint)listSz) }; if (container.ItemList != IntPtr.Zero) { IntPtr baseAddr = config.MemoryManager.Lock(container.ItemList); try { int offset = 0; foreach (var it in value.ItemList) { baseAddr.WriteValue(ref offset, value.Type, it); } } finally { config.MemoryManager.Unlock(container.ItemList); } try { baseAddr = config.MemoryManager.Lock(twCap.hContainer); Marshal.StructureToPtr(container, baseAddr, false); } finally { config.MemoryManager.Unlock(twCap.hContainer); } } else { config.MemoryManager.Free(twCap.hContainer); } } return(twCap); }
/// <summary> /// Generates a <see cref="TW_CAPABILITY"/> using single value (aka TW_ONEVALUE). /// </summary> /// <typeparam name="T"></typeparam> /// <param name="cap"></param> /// <param name="type"></param> /// <param name="value"></param> /// <returns></returns> public TW_CAPABILITY Generate <T>(CapabilityId cap, ItemType type, T value) { // size of data + uint16 item type var valueSz = type.GetSize(); if (valueSz < 4) { valueSz = 4; // onevalue container value minimum is 32bit } var memSz = valueSz + 2; // + item type field var twCap = new TW_CAPABILITY { Capability = cap, ContainerType = ContainerType.OneValue, hContainer = config.MemoryManager.Allocate((uint)memSz) }; if (twCap.hContainer != IntPtr.Zero) { IntPtr baseAddr = config.MemoryManager.Lock(twCap.hContainer); try { int offset = 0; // TODO: type size may be different on mac baseAddr.WriteValue(ref offset, ItemType.UInt16, value); // ONEVALUE is special in value can be uint32 or string // if less than uint32 put it in lower word // (string value seems undocumented but internet says put it as-is and not a pointer) if (valueSz < 4) { Marshal.WriteInt16(baseAddr, offset, 0); offset += 2; } baseAddr.WriteValue(ref offset, type, value); } finally { config.MemoryManager.Unlock(twCap.hContainer); } } return(twCap); }
/// <summary> /// Capability triplet call with custom DAT and message. /// </summary> /// <param name="DAT"></param> /// <param name="message"></param> /// <param name="capability"></param> /// <returns></returns> public ReturnCode Custom(DataArgumentType DAT, Message message, ref TW_CAPABILITY capability) { if (Is32Bit) { if (IsWin) { return(NativeMethods.DsmWin32(Session.Config.App32, Session.CurrentSource.Identity32, DataGroups.Control, DAT, message, ref capability)); } if (IsLinux) { return(NativeMethods.DsmLinux32(Session.Config.App32, Session.CurrentSource.Identity32, DataGroups.Control, DAT, message, ref capability)); } if (IsMac) { return(NativeMethods.DsmMac32(Session.Config.App32, Session.CurrentSource.Identity32, DataGroups.Control, DAT, message, ref capability)); } } if (IsWin) { return(NativeMethods.DsmWin64(Session.Config.App32, Session.CurrentSource.Identity32, DataGroups.Control, DAT, message, ref capability)); } if (IsLinux) { return(NativeMethods.DsmLinux64(Session.Config.App32, Session.CurrentSource.Identity32, DataGroups.Control, DAT, message, ref capability)); } if (IsMac) { return(NativeMethods.DsmMac64(Session.Config.App32, Session.CurrentSource.Identity32, DataGroups.Control, DAT, message, ref capability)); } return(ReturnCode.Failure); }
/// <summary> /// Generates a <see cref="TW_CAPABILITY"/> for use in capability negotiation /// using TWAIN's range value. /// </summary> /// <param name="cap"></param> /// <param name="value"></param> /// <returns></returns> public TW_CAPABILITY Generate(CapabilityId cap, TW_RANGE value) { var twCap = new TW_CAPABILITY { Capability = cap, ContainerType = ContainerType.Range, hContainer = config.MemoryManager.Allocate((uint)Marshal.SizeOf(typeof(TW_RANGE))) }; if (twCap.hContainer != IntPtr.Zero) { try { IntPtr baseAddr = config.MemoryManager.Lock(twCap.hContainer); Marshal.StructureToPtr(value, baseAddr, false); } finally { config.MemoryManager.Unlock(twCap.hContainer); } } return(twCap); }
/// <summary> /// Returns help text suitable for use in a GUI; for instance: "Specify the amount of detail in an /// image. Higher values result in more detail." for ICapXRESOLUTION. /// </summary> /// <param name="capability">The capability.</param> /// <returns></returns> public ReturnCode GetHelp(ref TW_CAPABILITY capability) { return(Custom(DataArgumentType.Capability, Message.GetHelp, ref capability)); }
/// <summary> /// Changes the Current Value(s) and Available Value(s) of the specified capability to those specified /// by the application. /// </summary> /// Current Values are set when the container is a TW_ONEVALUE or TW_ARRAY. Available and /// Current Values are set when the container is a TW_ENUMERATION or TW_RANGE. /// <param name="capability">The capability.</param> /// <returns></returns> public ReturnCode SetConstraint(ref TW_CAPABILITY capability) { return(Custom(DataArgumentType.Capability, Message.SetConstraint, ref capability)); }
/// <summary> /// This command resets all of the current values and constraints to their defaults for all of the /// negotiable capabilities supported by the driver. /// </summary> /// <param name="capability">The capability.</param> /// <returns></returns> public ReturnCode ResetAll(ref TW_CAPABILITY capability) { return(Custom(DataArgumentType.Capability, Message.ResetAll, ref capability)); }
/// <summary> /// Returns the Source’s support status of this capability. /// </summary> /// <param name="capability">The capability.</param> /// <returns></returns> public ReturnCode QuerySupport(ref TW_CAPABILITY capability) { return(Custom(DataArgumentType.Capability, Message.QuerySupport, ref capability)); }
/// <summary> /// Convert the contents of a capability to a string that we can show in /// our simple GUI... /// </summary> /// <param name="a_twcapability">A TWAIN structure</param> /// <returns>A CSV string of the TWAIN structure</returns> public string CapabilityToCsv(TW_CAPABILITY a_twcapability) { IntPtr intptr; IntPtr intptrLocked; TWTY ItemType; uint NumItems; // Handle the container... switch (a_twcapability.ConType) { default: return ("(unrecognized container)"); case TWON.ARRAY: { uint uu; CSV csvArray; // Mac has a level of indirection and a different structure (ick)... if (ms_platform == Platform.MACOSX) { // Crack the container... TW_ARRAY_MACOSX twarraymacosx = default(TW_ARRAY_MACOSX); intptrLocked = DsmMemLock(a_twcapability.hContainer); twarraymacosx = (TW_ARRAY_MACOSX)Marshal.PtrToStructure(intptrLocked, typeof(TW_ARRAY_MACOSX)); ItemType = (TWTY)twarraymacosx.ItemType; NumItems = twarraymacosx.NumItems; intptr = (IntPtr)((UInt64)intptrLocked + (UInt64)Marshal.SizeOf(twarraymacosx)); } else { // Crack the container... TW_ARRAY twarray = default(TW_ARRAY); intptrLocked = DsmMemLock(a_twcapability.hContainer); twarray = (TW_ARRAY)Marshal.PtrToStructure(intptrLocked, typeof(TW_ARRAY)); ItemType = twarray.ItemType; NumItems = twarray.NumItems; intptr = (IntPtr)((UInt64)intptrLocked + (UInt64)Marshal.SizeOf(twarray)); } // Start building the string... csvArray = Common(a_twcapability.Cap, a_twcapability.ConType, ItemType); csvArray.Add(NumItems.ToString()); // Tack on the stuff from the ItemList... for (uu = 0; uu < NumItems; uu++) { csvArray.Add(GetIndexedItem(ItemType, intptr, (int)uu)); } // All done... DsmMemUnlock(a_twcapability.hContainer); return (csvArray.Get()); } case TWON.ENUMERATION: { uint uu; CSV csvEnum; // Mac has a level of indirection and a different structure (ick)... if (ms_platform == Platform.MACOSX) { // Crack the container... TW_ENUMERATION_MACOSX twenumerationmacosx = default(TW_ENUMERATION_MACOSX); intptrLocked = DsmMemLock(a_twcapability.hContainer); twenumerationmacosx = (TW_ENUMERATION_MACOSX)Marshal.PtrToStructure(intptrLocked, typeof(TW_ENUMERATION_MACOSX)); ItemType = (TWTY)twenumerationmacosx.ItemType; NumItems = twenumerationmacosx.NumItems; intptr = (IntPtr)((UInt64)intptrLocked + (UInt64)Marshal.SizeOf(twenumerationmacosx)); // Start building the string... csvEnum = Common(a_twcapability.Cap, a_twcapability.ConType, ItemType); csvEnum.Add(NumItems.ToString()); csvEnum.Add(twenumerationmacosx.CurrentIndex.ToString()); csvEnum.Add(twenumerationmacosx.DefaultIndex.ToString()); } else { // Crack the container... TW_ENUMERATION twenumeration = default(TW_ENUMERATION); intptrLocked = DsmMemLock(a_twcapability.hContainer); twenumeration = (TW_ENUMERATION)Marshal.PtrToStructure(intptrLocked, typeof(TW_ENUMERATION)); ItemType = twenumeration.ItemType; NumItems = twenumeration.NumItems; intptr = (IntPtr)((UInt64)intptrLocked + (UInt64)Marshal.SizeOf(twenumeration)); // Start building the string... csvEnum = Common(a_twcapability.Cap, a_twcapability.ConType, ItemType); csvEnum.Add(NumItems.ToString()); csvEnum.Add(twenumeration.CurrentIndex.ToString()); csvEnum.Add(twenumeration.DefaultIndex.ToString()); } // Tack on the stuff from the ItemList... for (uu = 0; uu < NumItems; uu++) { csvEnum.Add(GetIndexedItem(ItemType, intptr, (int)uu)); } // All done... DsmMemUnlock(a_twcapability.hContainer); return (csvEnum.Get()); } case TWON.ONEVALUE: { CSV csvOnevalue; // Mac has a level of indirection and a different structure (ick)... if (ms_platform == Platform.MACOSX) { // Crack the container... TW_ONEVALUE_MACOSX twonevaluemacosx = default(TW_ONEVALUE_MACOSX); intptrLocked = DsmMemLock(a_twcapability.hContainer); twonevaluemacosx = (TW_ONEVALUE_MACOSX)Marshal.PtrToStructure(intptrLocked, typeof(TW_ONEVALUE_MACOSX)); ItemType = (TWTY)twonevaluemacosx.ItemType; intptr = (IntPtr)((UInt64)intptrLocked + (UInt64)Marshal.SizeOf(twonevaluemacosx)); } else { // Crack the container... TW_ONEVALUE twonevalue = default(TW_ONEVALUE); intptrLocked = DsmMemLock(a_twcapability.hContainer); twonevalue = (TW_ONEVALUE)Marshal.PtrToStructure(intptrLocked, typeof(TW_ONEVALUE)); ItemType = (TWTY)twonevalue.ItemType; intptr = (IntPtr)((UInt64)intptrLocked + (UInt64)Marshal.SizeOf(twonevalue)); } // Start building the string... csvOnevalue = Common(a_twcapability.Cap, a_twcapability.ConType, ItemType); // Tack on the stuff from the Item... csvOnevalue.Add(GetIndexedItem(ItemType, intptr, 0)); // All done... DsmMemUnlock(a_twcapability.hContainer); return (csvOnevalue.Get()); } case TWON.RANGE: { CSV csvRange; TW_RANGE twrange; TW_RANGE_MACOSX twrangemacosx; TW_RANGE_FIX32 twrangefix32; TW_RANGE_FIX32_MACOSX twrangefix32macosx; // Mac has a level of indirection and a different structure (ick)... twrange = default(TW_RANGE); if (ms_platform == Platform.MACOSX) { intptrLocked = DsmMemLock(a_twcapability.hContainer); twrangemacosx = (TW_RANGE_MACOSX)Marshal.PtrToStructure(intptrLocked, typeof(TW_RANGE_MACOSX)); twrangefix32macosx = (TW_RANGE_FIX32_MACOSX)Marshal.PtrToStructure(intptrLocked, typeof(TW_RANGE_FIX32_MACOSX)); twrange.ItemType = (TWTY)twrangemacosx.ItemType; twrange.MinValue = twrangemacosx.MinValue; twrange.MaxValue = twrangemacosx.MaxValue; twrange.StepSize = twrangemacosx.StepSize; twrange.DefaultValue = twrangemacosx.DefaultValue; twrange.CurrentValue = twrangemacosx.CurrentValue; twrangefix32.ItemType = (TWTY)twrangefix32macosx.ItemType; twrangefix32.MinValue = twrangefix32macosx.MinValue; twrangefix32.MaxValue = twrangefix32macosx.MaxValue; twrangefix32.StepSize = twrangefix32macosx.StepSize; twrangefix32.DefaultValue = twrangefix32macosx.DefaultValue; twrangefix32.CurrentValue = twrangefix32macosx.CurrentValue; } else { intptrLocked = DsmMemLock(a_twcapability.hContainer); twrange = (TW_RANGE)Marshal.PtrToStructure(intptrLocked, typeof(TW_RANGE)); twrangefix32 = (TW_RANGE_FIX32)Marshal.PtrToStructure(intptrLocked, typeof(TW_RANGE_FIX32)); } // Start the string... csvRange = Common(a_twcapability.Cap, a_twcapability.ConType, twrange.ItemType); // Tack on the data... switch ((TWTY)twrange.ItemType) { default: DsmMemUnlock(a_twcapability.hContainer); return ("(Get Capability: unrecognized data type)"); case TWTY.INT8: csvRange.Add(((char)(twrange.MinValue)).ToString()); csvRange.Add(((char)(twrange.MaxValue)).ToString()); csvRange.Add(((char)(twrange.StepSize)).ToString()); csvRange.Add(((char)(twrange.DefaultValue)).ToString()); csvRange.Add(((char)(twrange.CurrentValue)).ToString()); DsmMemUnlock(a_twcapability.hContainer); return (csvRange.Get()); case TWTY.INT16: csvRange.Add(((short)(twrange.MinValue)).ToString()); csvRange.Add(((short)(twrange.MaxValue)).ToString()); csvRange.Add(((short)(twrange.StepSize)).ToString()); csvRange.Add(((short)(twrange.DefaultValue)).ToString()); csvRange.Add(((short)(twrange.CurrentValue)).ToString()); DsmMemUnlock(a_twcapability.hContainer); return (csvRange.Get()); case TWTY.INT32: csvRange.Add(((int)(twrange.MinValue)).ToString()); csvRange.Add(((int)(twrange.MaxValue)).ToString()); csvRange.Add(((int)(twrange.StepSize)).ToString()); csvRange.Add(((int)(twrange.DefaultValue)).ToString()); csvRange.Add(((int)(twrange.CurrentValue)).ToString()); DsmMemUnlock(a_twcapability.hContainer); return (csvRange.Get()); case TWTY.UINT8: csvRange.Add(((byte)(twrange.MinValue)).ToString()); csvRange.Add(((byte)(twrange.MaxValue)).ToString()); csvRange.Add(((byte)(twrange.StepSize)).ToString()); csvRange.Add(((byte)(twrange.DefaultValue)).ToString()); csvRange.Add(((byte)(twrange.CurrentValue)).ToString()); DsmMemUnlock(a_twcapability.hContainer); return (csvRange.Get()); case TWTY.BOOL: case TWTY.UINT16: csvRange.Add(((ushort)(twrange.MinValue)).ToString()); csvRange.Add(((ushort)(twrange.MaxValue)).ToString()); csvRange.Add(((ushort)(twrange.StepSize)).ToString()); csvRange.Add(((ushort)(twrange.DefaultValue)).ToString()); csvRange.Add(((ushort)(twrange.CurrentValue)).ToString()); DsmMemUnlock(a_twcapability.hContainer); return (csvRange.Get()); case TWTY.UINT32: csvRange.Add(((uint)(twrange.MinValue)).ToString()); csvRange.Add(((uint)(twrange.MaxValue)).ToString()); csvRange.Add(((uint)(twrange.StepSize)).ToString()); csvRange.Add(((uint)(twrange.DefaultValue)).ToString()); csvRange.Add(((uint)(twrange.CurrentValue)).ToString()); DsmMemUnlock(a_twcapability.hContainer); return (csvRange.Get()); case TWTY.FIX32: csvRange.Add(((double)twrangefix32.MinValue.Whole + ((double)twrangefix32.MinValue.Frac / 65536.0)).ToString()); csvRange.Add(((double)twrangefix32.MaxValue.Whole + ((double)twrangefix32.MaxValue.Frac / 65536.0)).ToString()); csvRange.Add(((double)twrangefix32.StepSize.Whole + ((double)twrangefix32.StepSize.Frac / 65536.0)).ToString()); csvRange.Add(((double)twrangefix32.DefaultValue.Whole + ((double)twrangefix32.DefaultValue.Frac / 65536.0)).ToString()); csvRange.Add(((double)twrangefix32.CurrentValue.Whole + ((double)twrangefix32.CurrentValue.Frac / 65536.0)).ToString()); DsmMemUnlock(a_twcapability.hContainer); return (csvRange.Get()); } } } }
/// <summary> /// Issue capabilities commands... /// </summary> /// <param name="a_dg">Data group</param> /// <param name="a_msg">Operation</param> /// <param name="a_twcapability">CAPABILITY structure</param> /// <returns>TWAIN status</returns> public STS DatCapability(DG a_dg, MSG a_msg, ref TW_CAPABILITY a_twcapability) { STS sts; // Submit the work to the TWAIN thread... if ((m_threadTwain != null) && (m_threadTwain.ManagedThreadId != Thread.CurrentThread.ManagedThreadId)) { lock (m_lockTwain) { ThreadData threaddata = default(ThreadData); long lIndex = 0; // TBD: sometimes this doesn't work! Not sure why // yet, but a retry takes care of it. for (int ii = 0; ii < 5; ii++) { // Set our command variables... threaddata = default(ThreadData); threaddata.twcapability = a_twcapability; threaddata.dg = a_dg; threaddata.msg = a_msg; threaddata.dat = DAT.CAPABILITY; lIndex = m_twaincommand.Submit(threaddata); // Submit the command and wait for the reply... CallerToThreadSet(); ThreadToCallerWaitOne(); // Hmmm... if ( (a_msg == MSG.GETCURRENT) && (m_twaincommand.Get(lIndex).sts == STS.SUCCESS) && (m_twaincommand.Get(lIndex).twcapability.ConType == (TWON)0) && (m_twaincommand.Get(lIndex).twcapability.hContainer == IntPtr.Zero)) { Thread.Sleep(1000); continue; } // We're done... break; } // Return the result... a_twcapability = m_twaincommand.Get(lIndex).twcapability; sts = m_twaincommand.Get(lIndex).sts; // Clear the command variables... m_twaincommand.Delete(lIndex); } return (sts); } // Log it... if (Log.GetLevel() > 0) { if ((a_msg == MSG.SET) || (a_msg == MSG.SETCONSTRAINT)) { Log.LogSendBefore(a_dg.ToString(), DAT.CAPABILITY.ToString(), a_msg.ToString(), CapabilityToCsv(a_twcapability)); } else { string szCap = a_twcapability.Cap.ToString(); if (!szCap.Contains("_")) { szCap = "0x" + ((ushort)a_twcapability.Cap).ToString("X"); } Log.LogSendBefore(a_dg.ToString(), DAT.CAPABILITY.ToString(), a_msg.ToString(), szCap + ",0,0"); } } // Windows... if (ms_platform == Platform.WINDOWS) { // Issue the command... try { if (m_blUseLegacyDSM) { sts = (STS)WindowsTwain32DsmEntryCapability(ref m_twidentitylegacyApp, ref m_twidentitylegacyDs, a_dg, DAT.CAPABILITY, a_msg, ref a_twcapability); } else { sts = (STS)WindowsTwaindsmDsmEntryCapability(ref m_twidentitylegacyApp, ref m_twidentitylegacyDs, a_dg, DAT.CAPABILITY, a_msg, ref a_twcapability); } } catch { // The driver crashed... Log.LogSendAfter(STS.BUMMER.ToString(), ""); return (STS.BUMMER); } } // Linux... else if (ms_platform == Platform.LINUX) { // Issue the command... try { if (GetMachineWordBitSize() == 32) { sts = (STS)LinuxDsmEntryCapability(ref m_twidentitylegacyApp, ref m_twidentitylegacyDs, a_dg, DAT.CAPABILITY, a_msg, ref a_twcapability); } else { sts = (STS)Linux64DsmEntryCapability(ref m_twidentityApp, ref m_twidentityDs, a_dg, DAT.CAPABILITY, a_msg, ref a_twcapability); } } catch { // The driver crashed... Log.LogSendAfter(STS.BUMMER.ToString(), ""); return (STS.BUMMER); } } // Mac OS X, which has to be different... else if (ms_platform == Platform.MACOSX) { // Issue the command... try { sts = (STS)MacosxDsmEntryCapability(ref m_twidentitymacosxApp, ref m_twidentitymacosxDs, a_dg, DAT.CAPABILITY, a_msg, ref a_twcapability); } catch { // The driver crashed... Log.LogSendAfter(STS.BUMMER.ToString(), ""); return (STS.BUMMER); } } // Uh-oh... else { Log.LogSendAfter(STS.BUMMER.ToString(), ""); return (STS.BUMMER); } // Log it... if (Log.GetLevel() > 0) { if ((a_msg == MSG.RESETALL) || ((sts != STS.SUCCESS) && (sts != STS.CHECKSTATUS))) { Log.LogSendAfter(sts.ToString(), ""); } else { Log.LogSendAfter(sts.ToString(), CapabilityToCsv(a_twcapability)); } } // All done... return (AutoDatStatus(sts)); }
/// <summary> /// Convert the contents of a string into something we can poke into a /// TW_CAPABILITY structure... /// </summary> /// <param name="a_twcapability">A TWAIN structure</param> /// <param name="a_szSetting">A CSV string of the TWAIN structure</param> /// <param name="a_szValue">The container for this capability</param> /// <returns>True if the conversion is successful</returns> public bool CsvToCapability(ref TW_CAPABILITY a_twcapability, ref string a_szSetting, string a_szValue) { int ii; TWTY twty; uint u32NumItems; IntPtr intptr; string szResult; string[] asz; // We need some protection for this one... try { // Tokenize our values... asz = CSV.Parse(a_szValue); if (asz.GetLength(0) < 4) { a_szSetting = "Set Capability: (insufficient number of arguments)"; return (false); } // Set the capability from text or hex... try { a_twcapability.Cap = (CAP)Enum.Parse(typeof(CAP), asz[0], true); } catch { a_twcapability.Cap = (CAP)0xFFFF; } if ((a_twcapability.Cap == (CAP)0xFFFF) || !asz[0].Contains("_")) { a_twcapability.Cap = (CAP)Convert.ToUInt16(asz[0], 16); } // Set the container from text or decimal... try { a_twcapability.ConType = (TWON)Enum.Parse(typeof(TWON), asz[1].Replace("TWON_", ""), true); } catch { a_twcapability.ConType = (TWON)ushort.Parse(asz[1]); } // Set the item type from text or decimal... try { twty = (TWTY)Enum.Parse(typeof(TWTY), asz[2].Replace("TWTY_", ""), true); } catch { twty = (TWTY)ushort.Parse(asz[2]); } // Assign the new value... switch (a_twcapability.ConType) { default: a_szSetting = "(unrecognized container)"; return (false); case TWON.ARRAY: // Validate... if (asz.GetLength(0) < 4) { a_szSetting = "Set Capability: (insufficient number of arguments)"; return (false); } // Get the values... u32NumItems = uint.Parse(asz[3]); // Allocate the container (go for worst case, which is TW_STR255)... if (ms_platform == Platform.MACOSX) { // Allocate... a_twcapability.hContainer = DsmMemAlloc((uint)(Marshal.SizeOf(default(TW_ARRAY_MACOSX)) + (((int)u32NumItems + 1) * Marshal.SizeOf(default(TW_STR255))))); intptr = DsmMemLock(a_twcapability.hContainer); // Set the meta data... TW_ARRAY_MACOSX twarraymacosx = default(TW_ARRAY_MACOSX); twarraymacosx.ItemType = (uint)twty; twarraymacosx.NumItems = u32NumItems; Marshal.StructureToPtr(twarraymacosx, intptr, true); // Get the pointer to the ItemList... intptr = (IntPtr)((UInt64)intptr + (UInt64)Marshal.SizeOf(twarraymacosx)); } else { // Allocate... a_twcapability.hContainer = DsmMemAlloc((uint)(Marshal.SizeOf(default(TW_ARRAY)) + (((int)u32NumItems + 1) * Marshal.SizeOf(default(TW_STR255))))); intptr = DsmMemLock(a_twcapability.hContainer); // Set the meta data... TW_ARRAY twarray = default(TW_ARRAY); twarray.ItemType = twty; twarray.NumItems = u32NumItems; Marshal.StructureToPtr(twarray, intptr, true); // Get the pointer to the ItemList... intptr = (IntPtr)((UInt64)intptr + (UInt64)Marshal.SizeOf(twarray)); } // Set the ItemList... for (ii = 0; ii < u32NumItems; ii++) { szResult = SetIndexedItem(a_twcapability.ConType, twty, intptr, ii, asz[ii + 4]); if (szResult != "") { return (false); } } // All done... DsmMemUnlock(a_twcapability.hContainer); return (true); case TWON.ENUMERATION: // Validate... if (asz.GetLength(0) < 6) { a_szSetting = "Set Capability: (insufficient number of arguments)"; return (false); } // Get the values... u32NumItems = uint.Parse(asz[3]); // Allocate the container (go for worst case, which is TW_STR255)... if (ms_platform == Platform.MACOSX) { // Allocate... a_twcapability.hContainer = DsmMemAlloc((uint)(Marshal.SizeOf(default(TW_ENUMERATION_MACOSX)) + (((int)u32NumItems + 1) * Marshal.SizeOf(default(TW_STR255))))); intptr = DsmMemLock(a_twcapability.hContainer); // Set the meta data... TW_ENUMERATION_MACOSX twenumerationmacosx = default(TW_ENUMERATION_MACOSX); twenumerationmacosx.ItemType = (uint)twty; twenumerationmacosx.NumItems = u32NumItems; twenumerationmacosx.CurrentIndex = uint.Parse(asz[4]); twenumerationmacosx.DefaultIndex = uint.Parse(asz[5]); Marshal.StructureToPtr(twenumerationmacosx, intptr, true); // Get the pointer to the ItemList... intptr = (IntPtr)((UInt64)intptr + (UInt64)Marshal.SizeOf(twenumerationmacosx)); } else { // Allocate... a_twcapability.hContainer = DsmMemAlloc((uint)(Marshal.SizeOf(default(TW_ENUMERATION)) + (((int)u32NumItems + 1) * Marshal.SizeOf(default(TW_STR255))))); intptr = DsmMemLock(a_twcapability.hContainer); // Set the meta data... TW_ENUMERATION twenumeration = default(TW_ENUMERATION); twenumeration.ItemType = twty; twenumeration.NumItems = u32NumItems; twenumeration.CurrentIndex = uint.Parse(asz[4]); twenumeration.DefaultIndex = uint.Parse(asz[5]); Marshal.StructureToPtr(twenumeration, intptr, true); // Get the pointer to the ItemList... intptr = (IntPtr)((UInt64)intptr + (UInt64)Marshal.SizeOf(twenumeration)); } // Set the ItemList... for (ii = 0; ii < u32NumItems; ii++) { szResult = SetIndexedItem(a_twcapability.ConType, twty, intptr, ii, asz[ii + 6]); if (szResult != "") { return (false); } } // All done... DsmMemUnlock(a_twcapability.hContainer); return (true); case TWON.ONEVALUE: // Validate... if (asz.GetLength(0) < 4) { a_szSetting = "Set Capability: (insufficient number of arguments)"; return (false); } // Allocate the container (go for worst case, which is TW_STR255)... if (ms_platform == Platform.MACOSX) { // Allocate... a_twcapability.hContainer = DsmMemAlloc((uint)(Marshal.SizeOf(default(TW_ONEVALUE_MACOSX)) + Marshal.SizeOf(default(TW_STR255)))); intptr = DsmMemLock(a_twcapability.hContainer); // Set the meta data... TW_ONEVALUE_MACOSX twonevaluemacosx = default(TW_ONEVALUE_MACOSX); twonevaluemacosx.ItemType = (uint)twty; Marshal.StructureToPtr(twonevaluemacosx, intptr, true); // Get the pointer to the ItemList... intptr = (IntPtr)((UInt64)intptr + (UInt64)Marshal.SizeOf(twonevaluemacosx)); } else { // Allocate... a_twcapability.hContainer = DsmMemAlloc((uint)(Marshal.SizeOf(default(TW_ONEVALUE)) + Marshal.SizeOf(default(TW_STR255)))); intptr = DsmMemLock(a_twcapability.hContainer); // Set the meta data... TW_ONEVALUE twonevalue = default(TW_ONEVALUE); twonevalue.ItemType = twty; Marshal.StructureToPtr(twonevalue, intptr, true); // Get the pointer to the ItemList... intptr = (IntPtr)((UInt64)intptr + (UInt64)Marshal.SizeOf(twonevalue)); } // Set the Item... szResult = SetIndexedItem(a_twcapability.ConType, twty, intptr, 0, asz[3]); if (szResult != "") { return (false); } // All done... DsmMemUnlock(a_twcapability.hContainer); return (true); case TWON.RANGE: // Validate... if (asz.GetLength(0) < 8) { a_szSetting = "Set Capability: (insufficient number of arguments)"; return (false); } // Allocate the container (go for worst case, which is TW_STR255)... if (ms_platform == Platform.MACOSX) { // Allocate... a_twcapability.hContainer = DsmMemAlloc((uint)(Marshal.SizeOf(default(TW_RANGE_MACOSX)))); intptr = DsmMemLock(a_twcapability.hContainer); } else { // Allocate... a_twcapability.hContainer = DsmMemAlloc((uint)(Marshal.SizeOf(default(TW_RANGE)))); intptr = DsmMemLock(a_twcapability.hContainer); } // Set the Item... szResult = SetRangeItem(twty, intptr, asz); if (szResult != "") { return (false); } // All done... DsmMemUnlock(a_twcapability.hContainer); return (true); } } catch { a_szValue = "(data error)"; return (false); } }
private static extern UInt16 MacosxDsmEntryCapability ( ref TW_IDENTITY_MACOSX origin, ref TW_IDENTITY_MACOSX dest, DG dg, DAT dat, MSG msg, ref TW_CAPABILITY twcapability );
private static extern UInt16 Linux64DsmEntryCapability ( ref TW_IDENTITY origin, ref TW_IDENTITY dest, DG dg, DAT dat, MSG msg, ref TW_CAPABILITY twcapability );
private static extern UInt16 WindowsTwaindsmDsmEntryCapability ( ref TW_IDENTITY_LEGACY origin, ref TW_IDENTITY_LEGACY dest, DG dg, DAT dat, MSG msg, ref TW_CAPABILITY twcapability );
/// <summary> /// Issue capabilities commands... /// </summary> /// <param name="a_dg">Data group</param> /// <param name="a_msg">Operation</param> /// <param name="a_twcapability">CAPABILITY structure</param> /// <returns>TWAIN status</returns> public virtual STS DatCapability(DG a_dg, MSG a_msg, ref TW_CAPABILITY a_twcapability) { STS sts; // Submit the work to the TWAIN thread... if ((m_threadTwain != null) && (m_threadTwain.ManagedThreadId != Thread.CurrentThread.ManagedThreadId)) { lock (m_lockTwain) { // Set our command variables... m_threaddata = default(ThreadData); m_threaddata.twcapability = a_twcapability; m_threaddata.dg = a_dg; m_threaddata.msg = a_msg; m_threaddata.dat = DAT.CAPABILITY; // Submit the command and wait for the reply... CallerToThreadSet(); ThreadToCallerWaitOne(); // Return the result... a_twcapability = m_threaddata.twcapability; sts = m_threaddata.sts; // Clear the command variables... m_threaddata = default(ThreadData); } return (sts); } // Log it... if (Log.GetLevel() > 0) { Log.LogSendBefore(a_dg, DAT.CAPABILITY, a_msg, CapabilityToCsv(a_twcapability)); } // Windows... if (ms_platform == Platform.WINDOWS) { // Issue the command... try { if (m_blUseLegacyDSM) { sts = (STS)WindowsTwain32DsmEntryCapability(ref m_twidentitylegacyApp, ref m_twidentitylegacyDs, a_dg, DAT.CAPABILITY, a_msg, ref a_twcapability); } else { sts = (STS)WindowsTwaindsmDsmEntryCapability(ref m_twidentitylegacyApp, ref m_twidentitylegacyDs, a_dg, DAT.CAPABILITY, a_msg, ref a_twcapability); } } catch { // The driver crashed... Log.LogSendAfter(STS.BUMMER, ""); return (STS.BUMMER); } } // Linux... else if (ms_platform == Platform.LINUX) { // Issue the command... try { if (GetMachineWordBitSize() == 32) { sts = (STS)LinuxDsmEntryCapability(ref m_twidentitylegacyApp, ref m_twidentitylegacyDs, a_dg, DAT.CAPABILITY, a_msg, ref a_twcapability); } else { sts = (STS)Linux64DsmEntryCapability(ref m_twidentityApp, ref m_twidentityDs, a_dg, DAT.CAPABILITY, a_msg, ref a_twcapability); } } catch { // The driver crashed... Log.LogSendAfter(STS.BUMMER, ""); return (STS.BUMMER); } } // Mac OS X, which has to be different... else if (ms_platform == Platform.MACOSX) { // Issue the command... try { sts = (STS)MacosxDsmEntryCapability(ref m_twidentitymacosxApp, ref m_twidentitymacosxDs, a_dg, DAT.CAPABILITY, a_msg, ref a_twcapability); } catch { // The driver crashed... Log.LogSendAfter(STS.BUMMER, ""); return (STS.BUMMER); } } // Uh-oh... else { Log.LogSendAfter(STS.BUMMER, ""); return (STS.BUMMER); } // Log it... if (Log.GetLevel() > 0) { Log.LogSendAfter(sts, CapabilityToCsv(a_twcapability)); } // All done... return (AutoDatStatus(sts)); }