From 5b950ba056c1105f2ce0c9d1cde515a359ed8463 Mon Sep 17 00:00:00 2001 From: Ben Olden-Cooligan Date: Thu, 8 Nov 2018 15:20:34 -0500 Subject: [PATCH] Working wia device selection and property setting (minus subtypes) --- NAPS2.Core/NAPS2.Core.csproj | 1 + .../Scan/Wia/Native/NativeWiaMethods.cs | 13 +++++- NAPS2.Core/Scan/Wia/Native/NativeWiaObject.cs | 5 ++- NAPS2.Core/Scan/Wia/Native/WiaItemBase.cs | 9 +++++ .../Scan/Wia/Native/WiaItemExtensions.cs | 10 ++--- NAPS2.Core/Scan/Wia/Native/WiaProperty.cs | 37 +++++++++++++----- .../Scan/Wia/Native/WiaPropertyCollection.cs | 17 +++----- NAPS2.Core/Scan/Wia/Native/WiaPropertyId.cs | 2 + NAPS2.Core/Scan/Wia/Native/WiaPropertyType.cs | 15 +++++++ NAPS2.Core/Scan/Wia/WiaScanDriver.cs | 22 +++++------ NAPS2.WIA/NAPS2.WIA.cpp | Bin 11912 -> 14406 bytes 11 files changed, 91 insertions(+), 40 deletions(-) create mode 100644 NAPS2.Core/Scan/Wia/Native/WiaPropertyType.cs diff --git a/NAPS2.Core/NAPS2.Core.csproj b/NAPS2.Core/NAPS2.Core.csproj index 661a49733..2456e1ec5 100644 --- a/NAPS2.Core/NAPS2.Core.csproj +++ b/NAPS2.Core/NAPS2.Core.csproj @@ -213,6 +213,7 @@ + diff --git a/NAPS2.Core/Scan/Wia/Native/NativeWiaMethods.cs b/NAPS2.Core/Scan/Wia/Native/NativeWiaMethods.cs index 127ffbbe7..4badf82d4 100644 --- a/NAPS2.Core/Scan/Wia/Native/NativeWiaMethods.cs +++ b/NAPS2.Core/Scan/Wia/Native/NativeWiaMethods.cs @@ -25,8 +25,19 @@ namespace NAPS2.Scan.Wia.Native [DllImport("NAPS2.WIA.dll")] public static extern uint GetItemPropertyStorage(IntPtr item, out IntPtr propStorage); + public delegate void EnumPropertyCallback(int propId, [MarshalAs(UnmanagedType.LPWStr)] string propName, ushort propType); + [DllImport("NAPS2.WIA.dll")] - public static extern uint SetItemProperty(IntPtr item, int propId, int value); + public static extern uint EnumerateProperties(IntPtr propStorage, [MarshalAs(UnmanagedType.FunctionPtr)] EnumPropertyCallback func); + + [DllImport("NAPS2.WIA.dll")] + public static extern uint GetPropertyBstr(IntPtr propStorage, int propId, [MarshalAs(UnmanagedType.BStr), Out] out string value); + + [DllImport("NAPS2.WIA.dll")] + public static extern uint GetPropertyInt(IntPtr propStorage, int propId, [Out] out int value); + + [DllImport("NAPS2.WIA.dll")] + public static extern uint SetPropertyInt(IntPtr propStorage, int propId, int value); [DllImport("NAPS2.WIA.dll")] public static extern uint StartTransfer(IntPtr item, [Out] out IntPtr transfer); diff --git a/NAPS2.Core/Scan/Wia/Native/NativeWiaObject.cs b/NAPS2.Core/Scan/Wia/Native/NativeWiaObject.cs index c78cfef65..d7ccea679 100644 --- a/NAPS2.Core/Scan/Wia/Native/NativeWiaObject.cs +++ b/NAPS2.Core/Scan/Wia/Native/NativeWiaObject.cs @@ -41,7 +41,10 @@ namespace NAPS2.Scan.Wia.Native { if (!disposed) { - Marshal.Release(Handle); + if (Handle != IntPtr.Zero) + { + Marshal.Release(Handle); + } disposed = true; } } diff --git a/NAPS2.Core/Scan/Wia/Native/WiaItemBase.cs b/NAPS2.Core/Scan/Wia/Native/WiaItemBase.cs index 786f26ba9..a4d3e7234 100644 --- a/NAPS2.Core/Scan/Wia/Native/WiaItemBase.cs +++ b/NAPS2.Core/Scan/Wia/Native/WiaItemBase.cs @@ -35,5 +35,14 @@ namespace NAPS2.Scan.Wia.Native WiaException.Check(NativeWiaMethods.GetItem(Handle, name, out var itemHandle)); return new WiaItem(itemHandle); } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (disposing) + { + properties?.Dispose(); + } + } } } \ No newline at end of file diff --git a/NAPS2.Core/Scan/Wia/Native/WiaItemExtensions.cs b/NAPS2.Core/Scan/Wia/Native/WiaItemExtensions.cs index 8b39de480..3d3b96a07 100644 --- a/NAPS2.Core/Scan/Wia/Native/WiaItemExtensions.cs +++ b/NAPS2.Core/Scan/Wia/Native/WiaItemExtensions.cs @@ -16,25 +16,25 @@ namespace NAPS2.Scan.Wia.Native return device.Properties[WiaPropertyId.DIP_DEV_NAME].Value.ToString(); } - public static bool SupportsFeeder(this IWiaDeviceProps device) + public static bool SupportsFeeder(this WiaDevice device) { int capabilities = (int)device.Properties[WiaPropertyId.DPS_DOCUMENT_HANDLING_CAPABILITIES].Value; return (capabilities & WiaPropertyValue.FEEDER) != 0; } - public static bool SupportsDuplex(this IWiaDeviceProps device) + public static bool SupportsDuplex(this WiaDevice device) { int capabilities = (int)device.Properties[WiaPropertyId.DPS_DOCUMENT_HANDLING_CAPABILITIES].Value; return (capabilities & WiaPropertyValue.DUPLEX) != 0; } - public static bool FeederReady(this IWiaDeviceProps device) + public static bool FeederReady(this WiaDevice device) { int status = (int)device.Properties[WiaPropertyId.DPS_DOCUMENT_HANDLING_STATUS].Value; return (status & WiaPropertyValue.FEED_READY) != 0; } - public static void SetProperty(this WiaItem item, int propId, int value) + public static void SetProperty(this WiaItemBase item, int propId, int value) { var prop = item.Properties[propId]; if (prop != null) @@ -43,7 +43,7 @@ namespace NAPS2.Scan.Wia.Native } } - public static void SetPropertyRange(this WiaItem item, int propId, int value, int expectedMin, int expectedMax) + public static void SetPropertyRange(this WiaItemBase item, int propId, int value, int expectedMin, int expectedMax) { var prop = item.Properties[propId]; if (prop != null) diff --git a/NAPS2.Core/Scan/Wia/Native/WiaProperty.cs b/NAPS2.Core/Scan/Wia/Native/WiaProperty.cs index 8a4f76fd2..e2368c37e 100644 --- a/NAPS2.Core/Scan/Wia/Native/WiaProperty.cs +++ b/NAPS2.Core/Scan/Wia/Native/WiaProperty.cs @@ -6,29 +6,44 @@ namespace NAPS2.Scan.Wia.Native { public class WiaProperty { - private object value; - - protected internal WiaProperty(WiaItem owner, int id) + protected internal WiaProperty(IntPtr storage, int id, string name, ushort type) { - Owner = owner; + Storage = storage; Id = id; + Name = name; + Type = type; } - private WiaItem Owner { get; } + private IntPtr Storage { get; } public int Id { get; set; } + public string Name { get; } + + public ushort Type { get; } + // TODO: Full R/W impl public object Value { - get => value; + get + { + if (Type == WiaPropertyType.I4) + { + WiaException.Check(NativeWiaMethods.GetPropertyInt(Storage, Id, out int value)); + return value; + } + if (Type == WiaPropertyType.BSTR) + { + WiaException.Check(NativeWiaMethods.GetPropertyBstr(Storage, Id, out string value)); + return value; + } + throw new NotImplementedException("Not implemented property type"); + } set { - if (value is int valueInt) + if (Type == WiaPropertyType.I4) { - WiaException.Check(NativeWiaMethods.SetItemProperty(Owner.Handle, Id, valueInt)); - // TODO: Get the value from the backing in case it changes - this.value = value; + WiaException.Check(NativeWiaMethods.SetPropertyInt(Storage, Id, (int)value)); } else { @@ -47,6 +62,8 @@ namespace NAPS2.Scan.Wia.Native public object[] SubTypeValues { get; set; } + public override string ToString() => Name; + public enum SubTypes { None, diff --git a/NAPS2.Core/Scan/Wia/Native/WiaPropertyCollection.cs b/NAPS2.Core/Scan/Wia/Native/WiaPropertyCollection.cs index 686758019..0dba62ff8 100644 --- a/NAPS2.Core/Scan/Wia/Native/WiaPropertyCollection.cs +++ b/NAPS2.Core/Scan/Wia/Native/WiaPropertyCollection.cs @@ -1,28 +1,21 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Runtime.InteropServices; using NAPS2.Util; namespace NAPS2.Scan.Wia.Native { - public class WiaPropertyCollection + public class WiaPropertyCollection : NativeWiaObject { private readonly Dictionary propertyDict; - public WiaPropertyCollection(IntPtr propertyStorageHandle) + public WiaPropertyCollection(IntPtr propertyStorageHandle) : base(propertyStorageHandle) { propertyDict = new Dictionary(); - // TODO - try - { - } - finally - { - Marshal.Release(propertyStorageHandle); - } + WiaException.Check(NativeWiaMethods.EnumerateProperties(Handle, + (id, name, type) => propertyDict.Add(id, new WiaProperty(Handle, id, name, type)))); } - + public WiaProperty this[int propId] => propertyDict.Get(propId); } } diff --git a/NAPS2.Core/Scan/Wia/Native/WiaPropertyId.cs b/NAPS2.Core/Scan/Wia/Native/WiaPropertyId.cs index d50206ef5..83484768b 100644 --- a/NAPS2.Core/Scan/Wia/Native/WiaPropertyId.cs +++ b/NAPS2.Core/Scan/Wia/Native/WiaPropertyId.cs @@ -43,6 +43,8 @@ namespace NAPS2.Scan.Wia.Native public const int IPS_BRIGHTNESS = 6154; public const int IPS_CONTRAST = 6155; public const int IPS_ORIENTATION = 6156; + public const int IPS_MAX_HORIZONTAL_SIZE = 6165; + public const int IPS_MAX_VERTICAL_SIZE = 6166; public const int IPS_PAGES = 3096; } } diff --git a/NAPS2.Core/Scan/Wia/Native/WiaPropertyType.cs b/NAPS2.Core/Scan/Wia/Native/WiaPropertyType.cs new file mode 100644 index 000000000..f16c0dba8 --- /dev/null +++ b/NAPS2.Core/Scan/Wia/Native/WiaPropertyType.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace NAPS2.Scan.Wia.Native +{ + /// + /// Property type constants. + /// + public static class WiaPropertyType + { + public const int I4 = 3; + public const int BSTR = 8; + } +} \ No newline at end of file diff --git a/NAPS2.Core/Scan/Wia/WiaScanDriver.cs b/NAPS2.Core/Scan/Wia/WiaScanDriver.cs index db1f9d494..d920b3bae 100644 --- a/NAPS2.Core/Scan/Wia/WiaScanDriver.cs +++ b/NAPS2.Core/Scan/Wia/WiaScanDriver.cs @@ -44,7 +44,13 @@ namespace NAPS2.Scan.Wia { using (var deviceManager = new WiaDeviceManager()) { - return deviceManager.GetDeviceInfos().Select(x => new ScanDevice(x.Id(), x.Name())).ToList(); + return deviceManager.GetDeviceInfos().Select(x => + { + using (x) + { + return new ScanDevice(x.Id(), x.Name()); + } + }).ToList(); } } @@ -73,7 +79,7 @@ namespace NAPS2.Scan.Wia // TODO: Props ConfigureDeviceProps(device); - ConfigureItemProps(device, item); + ConfigureItemProps(item); // TODO: Format BMP "{B96B3CAB-0728-11D3-9D7B-0000F81EF32E}" // TODO: Arrrggg... WIA native UI is an option I'm supposed to support. @@ -115,7 +121,7 @@ namespace NAPS2.Scan.Wia } } - private void ConfigureItemProps(WiaDevice device, WiaItem item) + private void ConfigureItemProps(WiaItem item) { switch (ScanProfile.BitDepth) { @@ -143,14 +149,8 @@ namespace NAPS2.Scan.Wia int pageWidth = pageDimensions.WidthInThousandthsOfAnInch() * resolution / 1000; int pageHeight = pageDimensions.HeightInThousandthsOfAnInch() * resolution / 1000; - int horizontalSize = - (int)device.Properties[ScanProfile.PaperSource == ScanSource.Glass - ? WiaPropertyId.DPS_HORIZONTAL_BED_SIZE - : WiaPropertyId.DPS_HORIZONTAL_SHEET_FEED_SIZE].Value; - int verticalSize = - (int)device.Properties[ScanProfile.PaperSource == ScanSource.Glass - ? WiaPropertyId.DPS_VERTICAL_BED_SIZE - : WiaPropertyId.DPS_VERTICAL_SHEET_FEED_SIZE].Value; + int horizontalSize = (int)item.Properties[WiaPropertyId.IPS_MAX_HORIZONTAL_SIZE].Value; + int verticalSize = (int)item.Properties[WiaPropertyId.IPS_MAX_VERTICAL_SIZE].Value; int pagemaxwidth = horizontalSize * resolution / 1000; int pagemaxheight = verticalSize * resolution / 1000; diff --git a/NAPS2.WIA/NAPS2.WIA.cpp b/NAPS2.WIA/NAPS2.WIA.cpp index 78954419359832244baf0eb73866e4f065aa8a77..e58c4c76cf008be3ffcc049fb964b36ab399c82f 100644 GIT binary patch delta 1280 zcmbtUO-~b16um+a+FD}TK28r#^Uq!im+s>O#b?f%8ezrO&mUBU*VHPHYs$dpqa_n|HJ4|wGjthcF5H!)wJCD<&{ZPR9V zIOu3O<+t5#z9B`rV`T7H%sr7I3-L0lmZB2PV5f*VLphqIJn0kzQa$R78Anw27HzOI zF!s1D8jaA@PrSNqom0buqSPM6icx}BjxK?FiL!`!7EH1fN9;)F*ksTIImyl+T~2-y z7#-T7HROK>)=_+I!gCTsrv)J9X^y9ZUS5`pweX;`JqdrFS+oW@D0T6e)jgs7C1`$?+V4UcJ6nyL@L)L5TdCg^p@We!`dBrq zoP}2&iKkJoi&QZ8iXd0O>MG9Cb+w#qszunP@XW&|kGEK#Ly?+Vv3P9p3n?sam)GJN zZRu*$>b+|~bdv9f`rVy7sD^(RwUJdr6W>Crt%-{Ur>*nnPnlNC m+F9!a6j`Aibf5~096BU!u3*u$*v6T`ek1&kLK*LRNIw8OpAtU+ delta 333 zcmX?B&=I@gh4|!0MiP_rG*u?I$tg@uk&v0}Bso`J;VS*B8xA81-l_L7sE>>$B1 z`IWH%quS(nY4OPy40$FmP_meOM9yh4i+sT3ATXAiyg^2Vm6HJoCpRj{Pu?Rb#|UDn zPm%&LUdyOXc9SY$21);ym!JHFLvFHyh05duQZbYD6geipG7^}qBP}$!LQ@Lp6p6`` zq%|mViVoP$>d7gxUO*O_jhpop!&n8K7=jr>7=joS81fhr8FCp?CqGmdovfqEH91V3 l59%PU$y3zCL`@hB7%YKM2dGvJuKJ*w_~sV13G7U@3;>P}XD9#w