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); Listlit = 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(); }
Thursday, January 1, 2015
Enable/Disable, Start/Stop PnP device -- not for production
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/
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
Thursday, December 25, 2014
Manually add Connection Point support after ATL Simple object wizard already run
After running ATL COM Simple object wizard without check "Connection Points", manual steps are need to add this support. (1) myserver.h---IConnectionPointContainer/Impl, COM_MAP, IEvents #include "ATLProject1_i.h" #include "_IMyServerEvents_CP.h" class ATL_NO_VTABLE CMyServer : public CComObjectRootEx<CComSingleThreadModel>, public CComCoClass<CMyServer, &CLSID_MyServer>, public IConnectionPointContainerImpl<CMyServer>, public CProxy_IMyServerEvents<CMyServer>, public IDispatchImpl<IMyServer, &IID_IMyServer, &LIBID_ATLProject1Lib, /*wMajor =*/ 1, /*wMinor =*/ 0> { BEGIN_COM_MAP(CMyServer) COM_INTERFACE_ENTRY(IMyServer) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY(IConnectionPointContainer) END_COM_MAP() BEGIN_CONNECTION_POINT_MAP(CMyServer) CONNECTION_POINT_ENTRY(__uuidof(_IMyServerEvents)) END_CONNECTION_POINT_MAP() (2) .\atlproject1\atlproject1\atlproject1.vcxproj.filters -- need one include <ClInclude Include="ATLProject1_i.h"> <Filter>Generated Files</Filter> </ClInclude> <ClInclude Include="_IMyServerEvents_CP.h"> <Filter>Header Files</Filter> </ClInclude> <ClInclude Include="MyServer.h"> <Filter>Header Files</Filter> </ClInclude> </ItemGroup> (3).\atlproject1\atlproject1\atlproject1.vcxproj --- include .h for compiler <ItemGroup> <ClInclude Include="ATLProject1_i.h" /> <ClInclude Include="dllmain.h" /> <ClInclude Include="MyServer.h" /> <ClInclude Include="Resource.h" /> <ClInclude Include="stdafx.h" /> <ClInclude Include="targetver.h" /> <ClInclude Include="xdlldata.h" /> <ClInclude Include="_IMyServerEvents_CP.h" /> </ItemGroup> (4) .\atlproject1\atlproject1\atlproject1.idl -- disinterface and coclass library ATLProject1Lib { importlib("stdole2.tlb"); [ uuid(1D071C81-6C67-458F-9B35-992DBAE162D8) // one of these are duplicate uuid(118E250A-B298-4749-90D8-36C764237BA4) ] dispinterface _IMyServerEvents { properties: methods: }; [ uuid(48A5B08F-ED8F-4F1F-8344-5F7C913FB895) ] coclass MyServer { [default] interface IMyServer; [default, source] dispinterface _IMyServerEvents; }; }; Notes: (n1) to user Connection point, Add Method to _IMyServerEvents (Class View Context Menu) e.g. signature CB(int data). Then Add->Connection point onto CMyServer Class (again Class View Ctx Menu) select _IMyS erverEvents in Source Interface List. Now there will be a function Fire_CB to fire COM Event into WPF client (n2) MyServer.rgs need update ForceRemove {dispinterface _IMyServerEvents GUI in IDL} = s 'MyServer Class' (n3) Content of [project dir]\_IMyServerEvents_CP.h #pragma once using namespace ATL; templateclass CProxy_IMyServerEvents : public IConnectionPointImpl { // WARNING: This class may be regenerated by the wizard public: };
Saturday, November 29, 2014
IDataErroInfo in MVVM +Presenter
(1) MVVM INPC not compativle with Validation Event so OnPropertyChanged instead (2) Consider Grid Cell validation and Ok button CanExecute (3) IDXDataErrorInfo is for view,VM validation required custom code (4) IDXDataErrorInfo GetError Not implemented=> avoid clustered error on row level #region Validation for VM private bool _isValid; public bool IsValid { get { return _isValid; } set { if (_isValid != value) // check to reduce chking CanExcecute { _isValid = value; NotifyPropertyChanged(() => IsValid); } } } public void Validate() { int invalidChildrenCount= Children.Count(IsChildInvalid); bool allDataFieldValid = Validate("Pro1") == null && Validate("Pro2") ; IsValid= allDataFieldValid && invalidChildrenCount= == 0; } private bool IsChirldInvalid(ChirldGridVMData Chirld) { switch (SomeMode) { case "Mode1": if (Chirld.Validdate("Prop1") != null) return true; break; ... } switch (Mode2) { ... } return false; } private string Validate(string dataFieldName) { switch (dataFieldName) { case "VMProp1": if (string.IsNullOrEmpty(Description)) { return "Please enter ..."; // Non-empty description } break; ... } return null; } public string EnsureReferenceChirldChecked() { if (Chirlds.Count(l => l.IsRefChirld.HasValue && l.IsRefChirld.Value) >= 2) { return "Only one Chirld can be reference."; } if (Chirlds.Count(l => l.IsRefChirld.HasValue && l.IsRefChirld.Value) == 0) { return "At least one Chirld must be reference."; } return null; } #endregion #region IDataErrorInfo for View public string this[string dataFieldName] { get { //CommandManager.InvalidateRequerySuggested(); does not work var result = Validate(dataFieldName); return result; } } public string Error { get { // return this[string.Empty or Null] does not work return null; } } #endregion public class LegGridVMData : ViewModelItemBase, IDXDataErrorInfo { #region Fields private string _p1; public string VMP1 { get { return _p1;} set { _p1= value; NotifyPropertyChanged(() => WMP1); } } #endregion #region IDXDataErrorInfo for View public void GetError(ErrorInfo info) { // chose not to cluster error message to row level } public void GetPropertyError(string propertyName, ErrorInfo info) { info.ErrorType = ErrorType.Information; info.ErrorText= Validdate(propertyName); } #endregion #region Validation for VM public string Validdate(string propertyName) { switch (propertyName) { case "VMP1": if (string.IsNullOrEmpty(VMP1)) { return "Please select a VMp1"; } break; ... } return null; } #endregion private bool CanExecuteOk() { return ViewModel.IsValid; } private void TriggerViewModelChirldsValidation() { ViewModel.Chirlds = ViewModel.Chirlds; // Hack: assign itself to trigger Validation, w/o makeing NotifyPropertyChanged public. } void ListenToPropertyChangedEvent() { if (ViewModel == null || ViewModel.Chirlds == null) return; foreach (var l in ViewModel.Chirlds) l.PropertyChanged += OnPropertyChanged; ViewModel.PropertyChanged += OnPropertyChanged; } void OnPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { if (e.PropertyName == "IsValid") // IsValid changes => reevaluate CanExecute. { var cmd = ViewModel.OkCommand as DeChirldateCommand; if (cmd != null) cmd.RaiseCanExecuteChanged(); } else // otherwise, just do re-evaludation of IsValid { ViewModel.Validate(); } if (e.PropertyName == "IsRef") { TriggerViewModelChildrenValidation(); // Trigger one and only one Ref validation on Ref checkbox } }
Subscribe to:
Posts (Atom)