Saturday, February 28, 2015

INPC with Equality check


    public class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public void SetProperty<T>(ref T field, T value, Expression<Func<T>> exp)
        {
            if (EqualityComparer<T>.Default.Equals(field, value)) return;
            field = value;
            if (PropertyChanged != null)
            {
                MemberExpression me = exp.Body as MemberExpression;
                if (me != null && me.Member != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(me.Member.Name));
            }
        }
    }

Saturday, February 7, 2015

Code Snippet to walk Visual Tree for Dev Express GridControl Specifics


        private void AssociatedObject_LayoutUpdated(object sender, EventArgs e)
        {
            var v = AssociatedObject.View;

            HierarchyPanel hp = VisualTreeHelpers.FindChild(v);
            GridRow grs = VisualTreeHelpers.FindChild(hp);
            var ie = v.FindLogicalChildren();
            var ie2 = v.FindVisualChildren();
            int i1 = ie.Count();
            int i2 = ie2.Count();

            int i3 = hp.FindVisualChildren().Count();  
        }

        private GridControl dgc;
        private bool b;
        private void AssociatedObject_MasterRowExpanded(object sender, RowEventArgs e)
        {
             dgc= AssociatedObject.GetDetail(e.RowHandle) as GridControl;
             dgc.ItemsSourceChanged+=dgc_ItemsSourceChanged;
            var i = dgc.ItemsSource;
            var col = dgc.ItemsSource as ObservableCollection;
            col.CollectionChanged += col_CollectionChanged;

        }

        private void BlankoutColumns(int rowHandle)
        {
            var dgc = AssociatedObject.GetVisibleDetail(rowHandle) as GridControl;
            var dc = dgc.View.DataControl as GridControl;
            
            for (int i = 0; i < dc.VisibleRowCount; i++)
            {
                int h = dc.GetRowHandleByVisibleIndex(i);
                foreach (var c in  dc.Columns) 
                {
                    if (c.Name == "ChildName")
                    {
                        var v = dc.GetCellValue(h, c);
                       // c.CellTemplate = new DataTemplate(); // take out data template so next update never shown
                     //   dc.SetCellValue(h, c, null); // blank out already rendered text
                    }
                }
            }
        }
            DependencyPropertyDescriptor propertyDescriptor = DependencyPropertyDescriptor.FromProperty(GridViewBase.VisibleColumnsProperty, typeof(GridViewBase));
            propertyDescriptor.AddValueChanged(AssociatedObject.View, VisibleColumnsChanged);


Thursday, January 1, 2015

Enable/Disable, Start/Stop PnP device -- not for production



namespace JQD
{
    #region Enum and StructLayout, safe handle

    internal enum DiFunction
    {
        SelectDevice = 1,
        InstallDevice = 2,
        AssignResources = 3,
        Properties = 4,
        Remove = 5,
        FirstTimeSetup = 6,
        FoundDevice = 7,
        SelectClassDrivers = 8,
        ValidateClassDrivers = 9,
        InstallClassDrivers = (int)0xa,
        CalcDiskSpace = (int)0xb,
        DestroyPrivateData = (int)0xc,
        ValidateDriver = (int)0xd,
        Detect = (int)0xf,
        InstallWizard = (int)0x10,
        DestroyWizardData = (int)0x11,
        PropertyChange = (int)0x12,
        EnableClass = (int)0x13,
        DetectVerify = (int)0x14,
        InstallDeviceFiles = (int)0x15,
        UnRemove = (int)0x16,
        SelectBestCompatDrv = (int)0x17,
        AllowInstall = (int)0x18,
        RegisterDevice = (int)0x19,
        NewDeviceWizardPreSelect = (int)0x1a,
        NewDeviceWizardSelect = (int)0x1b,
        NewDeviceWizardPreAnalyze = (int)0x1c,
        NewDeviceWizardPostAnalyze = (int)0x1d,
        NewDeviceWizardFinishInstall = (int)0x1e,
        Unused1 = (int)0x1f,
        InstallInterfaces = (int)0x20,
        DetectCancel = (int)0x21,
        RegisterCoInstallers = (int)0x22,
        AddPropertyPageAdvanced = (int)0x23,
        AddPropertyPageBasic = (int)0x24,
        Reserved1 = (int)0x25,
        Troubleshooter = (int)0x26,
        PowerMessageWake = (int)0x27,
        AddRemotePropertyPageAdvanced = (int)0x28,
        UpdateDriverUI = (int)0x29,
        Reserved2 = (int)0x30
    }

    [Flags()]
    internal enum SetupDiGetClassDevsFlags
    {
        Default = 1,
        Present = 2,
        AllClasses = 4,
        Profile = 8,
        DeviceInterface = (int)0x10
    }


    internal enum StateChangeAction
    {
        Enable = 1,
        Disable = 2,
        PropChange = 3,
        Start = 4,
        Stop = 5
    }

    [Flags()]
    internal enum Scopes
    {
        Global = 1,
        ConfigSpecific = 2,
        ConfigGeneral = 4
    }

    [StructLayout(LayoutKind.Sequential)]
    internal struct PropertyChangeParameters
    {
        public int Size;
        // part of header. It's flattened out into 1 structure.
        public DiFunction DiFunction;
        public StateChangeAction StateChange;
        public Scopes Scope;
        public int HwProfile;
    }

    internal enum SetupApiError
    {
        NoAssociatedClass = unchecked((int)0xe0000200),
        ClassMismatch = unchecked((int)0xe0000201),
        DuplicateFound = unchecked((int)0xe0000202),
        NoDriverSelected = unchecked((int)0xe0000203),
        KeyDoesNotExist = unchecked((int)0xe0000204),
        InvalidDevinstName = unchecked((int)0xe0000205),
        InvalidClass = unchecked((int)0xe0000206),
        DevinstAlreadyExists = unchecked((int)0xe0000207),
        DevinfoNotRegistered = unchecked((int)0xe0000208),
        InvalidRegProperty = unchecked((int)0xe0000209),
        NoInf = unchecked((int)0xe000020a),
        NoSuchHDevinst = unchecked((int)0xe000020b),
        CantLoadClassIcon = unchecked((int)0xe000020c),
        InvalidClassInstaller = unchecked((int)0xe000020d),
        DiDoDefault = unchecked((int)0xe000020e),
        DiNoFileCopy = unchecked((int)0xe000020f),
        InvalidHwProfile = unchecked((int)0xe0000210),
        NoDeviceSelected = unchecked((int)0xe0000211),
        DevinfolistLocked = unchecked((int)0xe0000212),
        DevinfodataLocked = unchecked((int)0xe0000213),
        DiBadPath = unchecked((int)0xe0000214),
        NoClassInstallParams = unchecked((int)0xe0000215),
        FileQueueLocked = unchecked((int)0xe0000216),
        BadServiceInstallSect = unchecked((int)0xe0000217),
        NoClassDriverList = unchecked((int)0xe0000218),
        NoAssociatedService = unchecked((int)0xe0000219),
        NoDefaultDeviceInterface = unchecked((int)0xe000021a),
        DeviceInterfaceActive = unchecked((int)0xe000021b),
        DeviceInterfaceRemoved = unchecked((int)0xe000021c),
        BadInterfaceInstallSect = unchecked((int)0xe000021d),
        NoSuchInterfaceClass = unchecked((int)0xe000021e),
        InvalidReferenceString = unchecked((int)0xe000021f),
        InvalidMachineName = unchecked((int)0xe0000220),
        RemoteCommFailure = unchecked((int)0xe0000221),
        MachineUnavailable = unchecked((int)0xe0000222),
        NoConfigMgrServices = unchecked((int)0xe0000223),
        InvalidPropPageProvider = unchecked((int)0xe0000224),
        NoSuchDeviceInterface = unchecked((int)0xe0000225),
        DiPostProcessingRequired = unchecked((int)0xe0000226),
        InvalidCOInstaller = unchecked((int)0xe0000227),
        NoCompatDrivers = unchecked((int)0xe0000228),
        NoDeviceIcon = unchecked((int)0xe0000229),
        InvalidInfLogConfig = unchecked((int)0xe000022a),
        DiDontInstall = unchecked((int)0xe000022b),
        InvalidFilterDriver = unchecked((int)0xe000022c),
        NonWindowsNTDriver = unchecked((int)0xe000022d),
        NonWindowsDriver = unchecked((int)0xe000022e),
        NoCatalogForOemInf = unchecked((int)0xe000022f),
        DevInstallQueueNonNative = unchecked((int)0xe0000230),
        NotDisableable = unchecked((int)0xe0000231),
        CantRemoveDevinst = unchecked((int)0xe0000232),
        InvalidTarget = unchecked((int)0xe0000233),
        DriverNonNative = unchecked((int)0xe0000234),
        InWow64 = unchecked((int)0xe0000235),
        SetSystemRestorePoint = unchecked((int)0xe0000236),
        IncorrectlyCopiedInf = unchecked((int)0xe0000237),
        SceDisabled = unchecked((int)0xe0000238),
        UnknownException = unchecked((int)0xe0000239),
        PnpRegistryError = unchecked((int)0xe000023a),
        RemoteRequestUnsupported = unchecked((int)0xe000023b),
        NotAnInstalledOemInf = unchecked((int)0xe000023c),
        InfInUseByDevices = unchecked((int)0xe000023d),
        DiFunctionObsolete = unchecked((int)0xe000023e),
        NoAuthenticodeCatalog = unchecked((int)0xe000023f),
        AuthenticodeDisallowed = unchecked((int)0xe0000240),
        AuthenticodeTrustedPublisher = unchecked((int)0xe0000241),
        AuthenticodeTrustNotEstablished = unchecked((int)0xe0000242),
        AuthenticodePublisherNotTrusted = unchecked((int)0xe0000243),
        SignatureOSAttributeMismatch = unchecked((int)0xe0000244),
        OnlyValidateViaAuthenticode = unchecked((int)0xe0000245)
    }

    [StructLayout(LayoutKind.Sequential)]
    internal struct DeviceInfoData
    {
        public int Size;
        public Guid ClassGuid;
        public int DevInst;
        public IntPtr Reserved;
    }

    internal class SafeDeviceInfoSetHandle : SafeHandleZeroOrMinusOneIsInvalid
    {

        public SafeDeviceInfoSetHandle()
            : base(true)
        {
        }

        protected override bool ReleaseHandle()
        {
            return NativeMethods.SetupDiDestroyDeviceInfoList(this.handle);
        }

    }

    #endregion

    internal class NativeMethods
    {

        private const string setupapi = @"setupapi.dll";

        private NativeMethods()
        {
        }

        [DllImport(@"setupapi.dll", SetLastError = true)]
        public static extern bool SetupDiClassGuidsFromName(string ClassName, ref Guid ClassGuidArray1stItem, UInt32 ClassGuidArraySize, out UInt32 RequiredSize);

        [DllImport(setupapi, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool SetupDiCallClassInstaller(DiFunction installFunction, SafeDeviceInfoSetHandle deviceInfoSet, [In()]
ref DeviceInfoData deviceInfoData);

        [DllImport(setupapi, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool SetupDiEnumDeviceInfo(SafeDeviceInfoSetHandle deviceInfoSet, int memberIndex, ref DeviceInfoData deviceInfoData);

        [DllImport(setupapi, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode, SetLastError = true)]
        public static extern SafeDeviceInfoSetHandle SetupDiGetClassDevs([In()]ref Guid classGuid, [MarshalAs(UnmanagedType.LPWStr)]string enumerator, IntPtr hwndParent, SetupDiGetClassDevsFlags flags);

        [DllImport(@"setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool SetupDiGetDeviceInstanceId(
         IntPtr DeviceInfoSet,
         ref DeviceInfoData did,
         [MarshalAs(UnmanagedType.LPTStr)] StringBuilder DeviceInstanceId,
         int DeviceInstanceIdSize,
         out int RequiredSize
        );

        [SuppressUnmanagedCodeSecurity()]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [DllImport(setupapi, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool SetupDiDestroyDeviceInfoList(IntPtr deviceInfoSet);

        [DllImport(setupapi, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool SetupDiSetClassInstallParams(SafeDeviceInfoSetHandle deviceInfoSet, [In()]ref DeviceInfoData deviceInfoData, [In()]ref PropertyChangeParameters classInstallParams, int classInstallParamsSize);

        [DllImport("setupapi.dll", CharSet = CharSet.Auto)]
        public static extern int CM_Get_Device_ID(
           UInt32 dnDevInst,
           IntPtr buffer,
           int bufferLen,
           int flags
        );
    }
}


        private void Button_Click_2(object sender, RoutedEventArgs e)
        {
            bool enable = true;
            NewMethod(enable);
        }

        private static void NewMethod(bool enable)
        {
            Guid classGuid = new Guid("745a17a0-74d3-11d0-b6fe-00a0c90f57da");
            JQD.SafeDeviceInfoSetHandle handle = JQD.NativeMethods.SetupDiGetClassDevs(ref classGuid, null, IntPtr.Zero, JQD.SetupDiGetClassDevsFlags.Present);

            List lit = new List();
            JQD.DeviceInfoData[] diDataAll = GetDeviceInfoData(handle);
           
            foreach (JQD.DeviceInfoData did in diDataAll)
            {
                int nBytes = 32;
                IntPtr ptrInstanceBuf = Marshal.AllocHGlobal(nBytes);
                JQD.NativeMethods.CM_Get_Device_ID((uint)did.DevInst, ptrInstanceBuf, nBytes, 0);
                string InstanceID = Marshal.PtrToStringAuto(ptrInstanceBuf);
                if (InstanceID.Contains(@"VID_053A&PID_0B01"))
                {
                    lit.Add(did);
                }

                Marshal.FreeHGlobal(ptrInstanceBuf);
            }
            //return;
            //foreach (JQD.DeviceInfoData did in lit)
            //{
                JQD.DeviceInfoData diData = lit[0];

                JQD.PropertyChangeParameters @params = new JQD.PropertyChangeParameters();

                @params.Size = 8;
                @params.DiFunction = JQD.DiFunction.PropertyChange;
                @params.Scope = JQD.Scopes.Global;
                if (enable)
                {
                    @params.StateChange = JQD.StateChangeAction.Start;
                }
                else
                {
                    @params.StateChange = JQD.StateChangeAction.Stop;
                }

                bool result = JQD.NativeMethods.SetupDiSetClassInstallParams(handle, ref diData, ref @params, Marshal.SizeOf(@params));

                result = JQD.NativeMethods.SetupDiCallClassInstaller(JQD.DiFunction.PropertyChange, handle, ref diData);
            //}
        }

        private static JQD.DeviceInfoData[] GetDeviceInfoData(JQD.SafeDeviceInfoSetHandle handle)
        {
            List data = new List();
            JQD.DeviceInfoData did = new JQD.DeviceInfoData();
            int didSize = Marshal.SizeOf(did);
            did.Size = didSize;
            int index = 0;
            while (JQD.NativeMethods.SetupDiEnumDeviceInfo(handle, index, ref did))
            {
                data.Add(did);
                index += 1;
                did = new JQD.DeviceInfoData();
                did.Size = didSize;
            }
            return data.ToArray();
        }

Query PnP device health Status


            string VendorMatching = "VID_053A&PID_0B01"; // Vendor Id Prod Id Minor Revisioin
            using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_PnPEntity")) //Win32_PnPEntity Win32_USBHub
            {
                foreach (ManagementObject queryObj in searcher.Get())
                {
                    var v = new
                    {
                        ConfigManagerErrorCode = queryObj.Properties["ConfigManagerErrorCode"].Value,
                        Status = queryObj.Properties["Status"].Value,
                        StatusInfo = queryObj.Properties["StatusInfo"].Value,
                        Availability = queryObj.Properties["Availability"].Value,
                        LastErrorCode = queryObj.Properties["LastErrorCode"].Value,

                        DeviceID = queryObj.Properties["DeviceID"].Value,
                        PNPDeviceID = queryObj.Properties["PNPDeviceID"].Value,
                        ClassGuid = queryObj.Properties["ClassGuid"].Value,                        
                        HardwareID = queryObj.Properties["HardwareID"].Value,
                    };
                    if (v.DeviceID.ToString().Contains(VendorMatching)) 
                        
                        Debug.WriteLine(v);
                }
            }

// Win32_PnPEntity class has Error Code
// { ConfigManagerErrorCode = 0, Status = OK, StatusInfo = , Availability = , LastErrorCode = , DeviceID = HID\VID_053A&PID_0B01&MI_01&COL04\9&98E7406&0&0003, PNPDeviceID = HID\VID_053A&PID_0B01&MI_01&COL04\9&98E7406&0&0003, ClassGuid = {745a17a0-74d3-11d0-b6fe-00a0c90f57da}, HardwareID = System.String[] }

WMI USB Play and Play Device Add, Remove and Modify Event Watcher


        private ManagementEventWatcher watcherAttach;
        private ManagementEventWatcher watcherRemove;
        private ManagementEventWatcher watcherMod;

            watcherAttach = new ManagementEventWatcher();

              //object sender, EventArrivedEventArgs e
            watcherAttach.EventArrived += (s,e) =>
                {
                    var propData = e.NewEvent.Properties["TargetInstance"];
                    var mbObj = propData.Value as ManagementBaseObject;
                    if (mbObj.Properties["DeviceID"].Value.ToString().Contains(@"HID\VID_053A&PID_0B01"))
                    {

                     // Instance Id can be passed into various API  instId = queryObj.GetPropertyValue("PNPDeviceID").ToString();
                        Debug.WriteLine("Preh device added");
                    }
                };
            watcherAttach.Query = new WqlEventQuery("SELECT * FROM __InstanceCreationEvent " +
               "WITHIN 2 "+
              "WHERE TargetInstance ISA 'Win32_PnPEntity'");
            watcherAttach.Start();


            watcherRemove.Query =  new WqlEventQuery("SELECT * FROM __InstanceModificationEvent " +
               "WITHIN 2 " +
              "WHERE TargetInstance ISA 'Win32_PnPEntity'");

            watcherMod.Query =  new WqlEventQuery("SELECT * FROM __InstanceDeletionEvent " +
               "WITHIN 2 " +
              "WHERE TargetInstance ISA 'Win32_PnPEntity'");


            watcherAttach.Stop();
            watcherRemove.Stop();
            watcherAttach.Dispose();
            watcherRemove.Dispose();

Monday, December 29, 2014

Calling Win32 DLL from 64-bit WPF through ATL 32-bit Surrogate COM

(1) How to tell if a DLL is 32-bit or 64-bit

 dumpbin /headers MyServer.dll to tell by file Header x86 or x64

(2) Run 32-Bit COM in surrogate Procese so can be called from 64-bit WPF.(one kind of IPC)
       http://www.gfi.com/blog/32bit-object-64bit-environment/ 


 
  • Locate your COM object GUID under the HKey_Classes_Root\Wow6432Node\CLSID\[GUID]
  • Once located add a new REG_SZ (string) Value. Name should be AppID and data should be the same COM object GUID you have just searched for
  • Add a new key under HKey_Classes_Root\Wow6432Node\AppID\ The new key should be called the same as the com object GUID
  • Under the new key you just added, add a new REG_SZ (string) Value, and call it DllSurrogate. Leave the value empty
  • Create a new Key under HKey_Local_Machine\Software\Classes\AppID\ Again the new key should be called the same as the COM object’s GUID. No values are necessary to be added under this key.
  • (3) Step-by-step ALT 32-bit COM Creation (check to make sure project properties are x86) http://msdn.microsoft.com/en-us/library/dssw0ch4%28d=printer,v=vs.90%29.aspx http://msdn.microsoft.com/en-us/library/9yb4317s.aspx Note that C# COM is not usable in (2), especially HKey_Classes_Root\Wow6432Node\CLSID\[GUID] is not there. Also each build of ATL COM project will override this location and need to add back AppID={Guid} (4) A good overall review of 64-bit calling 32-bit using IPC http://blog.mattmags.com/2007/06/30/accessing-32-bit-dlls-from-64-bit-code/ (5) Dynamic Loading Win32 DLL to access its functions: #pragma hdrstop #pragma package(smart_init) // CObject1 HINSTANCE hMWXUSB=0; typedef int (__cdecl *MYPROC)(LPWSTR); typedef unsigned char (ACCEPT_LED)(int data); ACCEPT_LED *lpacceptled; typedef unsigned char (OPEN_USB)(void); OPEN_USB *lpopenusb; STDMETHODIMP CObject1::get_GetANum(SHORT* pVal) { hMWXUSB=LoadLibrary(L"MWXUSB.DLL"); MYPROC Accept_LED; //Accept_LED = (MYPROC) GetProcAddress(hMWXUSB, "Accept_LED"); if( (hMWXUSB = LoadLibrary(L"MWXUSB.DLL")) == NULL ) { *pVal=-5; return S_OK; } if( (lpopenusb=(OPEN_USB*)GetProcAddress(hMWXUSB,"Open_USB" ))==NULL ) { *pVal=-6; return S_OK; } unsigned char ucOpen; ucOpen = (*lpopenusb)(); if( (lpacceptled=(ACCEPT_LED*)GetProcAddress(hMWXUSB,"Accept_LED" ))==NULL ) { *pVal=-1105; return S_OK; } unsigned char ch; ch = (*lpacceptled)(1); if(ch) { *pVal=-2105; return S_OK; } *pVal=105; return S_OK; }

    Saturday, December 27, 2014

    Call 3rd party DLL from ATL COM

    (1) use tool to generate def and .lib from DLL ( assuming no header file)
        http://purefractalsolutions.com/show.php?a=utils/expdef
    
    (2) VC++ project linker-->input additional dependency
    
    (3) declare and use in CPP
    
    extern "C"   unsigned char Open_USB();
    extern "C"   unsigned char Accept_LED(int value);
    extern "C"  void Set_Callback(void* pAny);
    
    void(__stdcall*p)(int);  // calling convention matching far pascal, for most c function
    
    //void __cdecl* p;  // ptrAny
    
    
    static void __stdcall CB1(int value)  {..} instance function would hast this->* so callback must use static to remove this.
    
     p = &CB1;
     ::Open_USB();
     ::Accept_LED(0);
     ::Set_Callback(p);
    
    again cannot use __cdecl must use __stdcall. It turns out Calling Conversion even affect [DllImport] when re-target .net 4.0 from .net 4.0, must specify CDecl in DllImports