/// <summary> /// This function starts the watchdog. This method must be called after instantiating a watchdog /// in order for the watchdog to actually begin, umm, "watching". If the watchdog is paused by calling /// the Stop() method, then it may be resumed by calling this Start() method. /// </summary> /// <see cref="https://msdn.microsoft.com/en-us/library/ee482881(v=winembedded.60).aspx"/> public void Start() { if (_handle == IntPtr.Zero) { return; } // TRUE indicates success. if (!WinCeApi.StartWatchDogTimer(_handle, 0)) { // Failed _lastError = Marshal.GetLastWin32Error(); // only seems reliable if StartWatchDogTimer returns FALSE if (_lastError == ERROR_INVALID_HANDLE) { Log.Error(string.Format("WATCHDOG: Failed to start \"{0}\" watchdog due to invalid handle, GetLastWin32Error={1}.", _name, _lastError)); } else if (_lastError == ERROR_ALREADY_INITIALIZED) { Log.Error(string.Format("WATCHDOG: Failed to start \"{0}\" watchdog as it was already initialized, GetLastWin32Error={1}.", _name, _lastError)); } else { Log.Error(string.Format("WATCHDOG: Failed to start \"{0}\" watchdog, GetLastWin32Error={1}.", _name, _lastError)); } } else if (_logSuccessMsg) { // Success Log.Debug(string.Format("WATCHDOG: Success starting watchdog \"{0}\" with a period of {1} seconds.", _name, _periodSeconds)); } }
/// <summary> /// Return the system's current "boot vars" /// </summary> /// <returns></returns> static internal BootVars Load() { BootVars bootVars = new BootVars(); bool success = false; try { unsafe { success = bootvars_read(ref bootVars); // Will set LastError on failure. } if (!success) { int lastError = WinCeApi.GetLastError(); throw new ConfigurationException(string.Format("Error {0} reading BootVars", lastError)); } } catch (ConfigurationException) { throw; } catch (Exception ex) { throw new ConfigurationException("Error reading BootVars", ex); } finally { bootvars_deinit(); } return(bootVars); }
/// <summary> /// Constructor. /// </summary> /// <param name="watchDogName"> /// Name of the watchdog timer to be created. Every watchdog must have a unique name. /// </param> /// <param name="period"> /// Watchdog period, in milliseconds. If the watchdog is not refreshed /// after 'period' milliseconds is elapsed,then the watchdog will initate a reboot. /// </param> /// <see cref="https://msdn.microsoft.com/en-US/library/ee482966(v=winembedded.60).aspx"/> public WatchDog(string name, int period, bool logSuccessMsg) { Log.Assert(string.IsNullOrEmpty(name) == false, "WatchDog 'name' must be specified."); Log.Assert(period > 0, "WatchDog 'period' must be specified."); _name = name; _period = period; _periodSeconds = period / 1000; _logSuccessMsg = logSuccessMsg; // We can't let the watchdog run when using Visual Studio debugger, // because the watchdog might reboot the device when we stop at a breakpoint. #if DEBUG Log.Debug(string.Format("WATCHDOG: \"{0}\" not created because this is a Debug build.", name)); #else // A handle to the watchdog timer indicates success. _handle = WinCeApi.CreateWatchDogTimer(name, period, 0, WinCeApi.WDOG_RESET_DEVICE, 0, 0); _lastError = Marshal.GetLastWin32Error(); if (_handle == IntPtr.Zero) { Log.Error(string.Format("WATCHDOG: Failed to create watchdog \"{0}\", GetLastWin32Error={1}.", _name, _lastError)); } else if (_lastError == ERROR_ALREADY_EXISTS) // a new handle will be returned even if a watchdog with the same name exists { Log.Error(string.Format("WATCHDOG: Failed to create new watchdog as \"{0}\" already exists, GetLastWin32Error={1}.", _name, _lastError)); } else if (_logSuccessMsg) // error code of 0 is expected { Log.Debug(string.Format("WATCHDOG: Success creating watchdog \"{0}\", GetLastWin32Error={1}.", _name, _lastError)); } #endif }
/// <summary> /// Store the passed in "boot vars" as the system's current "boot vars". /// </summary> /// <param name="bootVars"></param> internal static void Save(BootVars bootVars) { bool success = false; try { unsafe { success = bootvars_write(ref bootVars); // Will set LastError on failure. } if (!success) { int lastError = WinCeApi.GetLastError(); throw new ConfigurationException(string.Format("Error {0} writing BootVars", lastError)); } } catch (ConfigurationException) { throw; } catch (Exception ex) { throw new ConfigurationException("Error writing BootVars", ex); } finally { bootvars_deinit(); } }
/// <summary> /// Checks a given pressure switch and returns. /// </summary> /// <param name="position">The position of the switch to check</param> /// <returns>True, if the pressure is good</returns> public static bool CheckPressureSwitch(int position) { if (!IsPressureSwitchPresent(position)) { return(true); } int success = 0; ushort data = 0; for (int attempt = 1; attempt <= 10; attempt++) { unsafe { success = GetPressureSwitchState(Convert.ToByte(position), &data); // returns 1 on success, 0 on error } if (success != 0) // success? { break; } Log.Error(string.Format("Error calling GetPressureSwitchState({0}), attempt {1}, GetLastError={2}", position, attempt, WinCeApi.GetLastError())); Thread.Sleep(100); } if (success == 0) // error? { int lastError = WinCeApi.GetLastError(); Log.Error(string.Format("Failure in GetPressureSwitchState({0}), GetLastError={1}", position, lastError)); throw new DeviceDriverException(DeviceHardware.PressureSwitchState, position, lastError); } return(data == 0); }
/// <summary> /// Returns a value indicating whether there is smart card present in a given slot. /// </summary> /// <param name="position">The card slot number</param> /// <returns>True if there is a card in the slot, 0 if not.</returns> public static bool IsCardPresent(int position) { ushort data = 0; int error = 0; for (int attempt = 1; attempt <= 10; attempt++) { unsafe { error = GetSmartCardPresence(Convert.ToByte(position), &data); // returns 1 on error, 0 on success } if (error == 0) // success? { break; } Log.Error(string.Format("Error calling GetSmartCardPresence({0}), attempt {1}, GetLastError={2}", position, attempt, WinCeApi.GetLastError())); Thread.Sleep(100); } if (error != 0) // error? { int lastError = WinCeApi.GetLastError(); Log.Error(string.Format("Failure in GetSmartCardPresence({0}), GetLastError={1}", position, lastError)); throw new DeviceDriverException(DeviceHardware.SmartCardPresence, position, lastError); } return(data != 0); }
private byte [] _GetRandomBytes(byte[] seed) { IntPtr prov; bool retVal = WinCeApi.CryptAcquireContext(out prov, null, null, (int)WinCeApi.SecurityProviderType.RSA_FULL, 0); retVal = _CryptGenRandom(prov, seed.Length, seed); WinCeApi.CryptReleaseContext(prov, 0); return(seed); }
private bool _CryptGenRandom(IntPtr hProv, int dwLen, byte[] pbBuffer) { if (System.Environment.OSVersion.Platform == PlatformID.WinCE) { return(WinCeApi.CryptGenRandomCe(hProv, dwLen, pbBuffer)); } else { return(WinCeApi.CryptGenRandomXp(hProv, dwLen, pbBuffer)); } }
/// <summary> /// This function refreshes ("pets") the watchdog. /// </summary> public void Refresh() { if (_handle == IntPtr.Zero) { return; } if (!WinCeApi.RefreshWatchDogTimer(_handle, 0)) { Log.Error(string.Format("WATCHDOG: Failed to refresh watchdog \"{0}\", GetLastWin32Error={1}.", _name, Marshal.GetLastWin32Error())); } }
/// <summary> /// This function stops (pauses) the watchdog. /// </summary> /// <see cref="https://msdn.microsoft.com/en-us/library/ee482847(v=winembedded.60).aspx"/> public void Stop() { if (_handle == IntPtr.Zero) { return; } // Returns TRUE if the function succeeds. if (!WinCeApi.StopWatchDogTimer(_handle, 0)) { // Failed _lastError = Marshal.GetLastWin32Error(); // only seems reliable if StopWatchDogTimer returns FALSE Log.Error(string.Format("WATCHDOG: Failed to stop watchdog \"{0}\", GetLastWin32Error={1}.", _name, _lastError)); } else if (_logSuccessMsg) { // Success Log.Debug(string.Format("WATCHDOG: Success stopping watchdog \"{0}\".", _name)); } }
/// <summary> /// This function releases the memory used by the watchdog timer. /// </summary> /// <see cref="https://msdn.microsoft.com/en-us/library/ee490442(v=winembedded.60).aspx"/> public void Close() { if (_handle == IntPtr.Zero) { return; } // Nonzero indicates success. Zero indicates failure. int result = WinCeApi.CloseHandle(_handle); if (result == 0) { // Failed _lastError = Marshal.GetLastWin32Error(); // only seems reliable if CloseHandle returns 0 Log.Error(string.Format("WATCHDOG: Failed to close watchdog \"{0}\", GetLastWin32Error={1}.", _name, _lastError)); } else if (_logSuccessMsg) { // Success Log.Debug(string.Format("WATCHDOG: Success({1}) closing watchdog \"{0}\".", _name, result)); } }
// <summary> /// return a SHA1 Hash on PPC and Smartphone /// </summary> /// <param name="pass"></param> /// <returns></returns> public static byte[] Sha1Hash(byte[] pass) { IntPtr hProv; bool retVal = WinCeApi.CryptAcquireContext(out hProv, null, null, (int)WinCeApi.SecurityProviderType.RSA_FULL, 0); IntPtr hHash; retVal = WinCeApi.CryptCreateHash(hProv, (int)WinCeApi.SecurityProviderType.CALG_SHA1, IntPtr.Zero, 0, out hHash); byte [] publicKey = pass; int publicKeyLen = publicKey.Length; retVal = WinCeApi.CryptHashData(hHash, publicKey, publicKeyLen, 0); int bufferLen = 20; // SHA1 size byte [] buffer = new byte[bufferLen]; retVal = WinCeApi.CryptGetHashParam(hHash, (int)WinCeApi.SecurityProviderType.HP_HASHVAL, buffer, ref bufferLen, 0); retVal = WinCeApi.CryptDestroyHash(hHash); retVal = WinCeApi.CryptReleaseContext(hProv, 0); return(buffer); }
/// <summary> /// /// </summary> /// <param name="args"></param> private void Run(string[] args) { Thread.CurrentThread.Name = "Master"; string applicationPath = Assembly.GetExecutingAssembly().GetName().CodeBase; Log.Info(Log.Dashes); Log.Info("STARTING " + applicationPath); foreach (string arg in args) { Log.Info(string.Format("arg: \"{0}\"", arg)); } Log.Debug(Thread.CurrentThread.Name + " ThreadId=" + Thread.CurrentThread.ManagedThreadId.ToString("x8")); Log.Info(Log.Dashes); // We want the Controller class to load now, so that it's static // constructor reads the config file. It's important to do this // before starting ANY of the service threads. Calling any // random property of the Controller class will cause the class to load. Controller.ApplicationPath = applicationPath; // Stop the pump and speaker on startup. This is primarily done because if // the debugger is stopped then restarted while the pump or speaker are on, then they're left on. // if we don't do this... Controller.TurnBuzzerOff(); Pump.Stop(); // Instantiate the console service immediately so that we can display // the "Starting" message ASAP. Note that we don't yet start the thread, // though, since we don't need (yet), to monitor for keypad input. LCD.Clear(); // This is the first time we're accessing the LCD class, so it's static constructor will be called here. LCD.SetLanguage(Configuration.DockingStation.Language); Controller.LastRebootTime = DateTime.UtcNow; Controller.FirmwareVersion = string.Format("{0}.{1}.{2}.{3}", Assembly.GetExecutingAssembly().GetName().Version.Major, Assembly.GetExecutingAssembly().GetName().Version.Minor, Assembly.GetExecutingAssembly().GetName().Version.Build, Assembly.GetExecutingAssembly().GetName().Version.Revision); _consoleService = new ConsoleService(this); Log.Debug(ConsoleService.Name + " has been created."); ConsoleService.Start(); // Calling InitializeState now will force the display to refresh and say "Starting" // right away. If we don't do this, it remains blank for a second or two. ConsoleService.InitializeState(); try { Configuration.ServiceMode = Controller.DetermineServiceMode(); } catch (Exception e) { Log.Error(e); } // Did something go wrong trying to read the configuration data from the flash memory? if (Configuration.HasConfigurationError && Configuration.DockingStation.IsSerialized()) { Controller.RunState |= Controller.State.ConfigError; } // Verify that we have a flash card. We can't do much of anything without one. bool haveFlashCard = FlashCard.WaitForMount(); if (haveFlashCard) { Log.Info("Found a mounted flash card"); } else { Log.Fatal("ERROR: FLASH CARD NOT FOUND."); Controller.RunState |= Controller.State.FlashCardError; } Log.Info(Log.Dashes); Log.Info("Firmware Version: " + Controller.FirmwareVersion); Log.Info(Log.Dashes); Controller.LogSystemInfo(); Log.Info(Log.Dashes); Controller.LogProcessorInfo(); Log.Info(Log.Dashes); Controller.LogMemory(); Log.Info(Log.Dashes); if (haveFlashCard) { FlashCard.Log(); Log.Info(Log.Dashes); } Log.Info("MAC Address: " + Controller.GetWiredNetworkAdapter().MacAddress); Log.Info(Log.Dashes); if (haveFlashCard) { DataAccess.DataAccess.StartInet(); DataAccess.DataAccess.StartInetQueue(); } // Before we can start the WebAppService, we need to initialize // the password used to login to it. // Note that for debug builds, we configure it to not use SLL. // There are two reasons for this... // 1) SSL slows done iNet DS Configurator, which is annoying // when we developers are constantly logging into it to use it. // 2) There is some sort of problem when Padarn is using SSL // that causes the Visual Studio debugger to lose its connections // to the device. #if DEBUG Configuration.ConfigureWebApp(Configuration.DockingStation.WebAppPassword, false); #else Configuration.ConfigureWebApp(Configuration.DockingStation.WebAppPassword, true); #endif if (Controller.RunState == Controller.State.OK) { InitializeWinsock(); } // AJAY: INS-8380 Service accounts need to perform auto-upgrade on instruments even in error/fail state - DSX // If service account is configured to override event priority in admin console, // this method reorders events that needs to be executed on docking station. if (Configuration.IsRepairAccount() && Configuration.DockingStation.UpgradeOnErrorFail) { ISC.iNet.DS.DomainModel.EventCode.SetEventPriorityForService(); } // Initialize, wire up and start all necessary services. // Note that this will be iterated every time any of the // services gets interrupted. // Create the services. Log.Debug("Creating services..."); _resourceService = new ResourceService(this); Log.Debug(ResourceService.Name + " has been created."); _reporterService = new ReporterService(this); Log.Debug(ReporterService.Name + " has been created."); _executerService = new ExecuterService(this); Log.Debug(ExecuterService.Name + " has been created."); _switchService = new SwitchService(this); Log.Debug(SwitchService.Name + " has been created."); _chargingService = new ChargingService(this); Log.Debug(ChargingService.Name + " has been created."); _webAppService = new WebAppService(this); Log.Debug(WebAppService.Name + " has been created."); _controllerWrapper = ControllerWrapper.Instance; _pumpWrapper = PumpManager.Instance; _lcdWrapper = LCDWrapper.Instance; _smartCardWrapper = SmartCardWrapper.Instance; // Start the services. Log.Debug("Starting service threads..."); if (Controller.RunState == Controller.State.OK) { ResourceService.Start(); } // Don't start the Switch, Charging, or Executer service if the DS has // not been serialized. Only the Configurator web app will be functional. if (Configuration.DockingStation.IsSerialized()) { ExecuterService.Start(); if (Controller.RunState == Controller.State.OK) { SwitchService.Start(); } if (Controller.RunState == Controller.State.OK) { ChargingService.Start(); } } else { // update the LCD ConsoleService.UpdateState(ConsoleState.NotSerialized); } if (Controller.RunState == Controller.State.OK) { ReporterService.Start(); } WebAppService.Start(); Log.Debug("Service threads started."); // the controller's static constructor will initialize the other logging settings, // but we always want to log all the initialization stuff above out the serial port Log.LogToSerialPort = Configuration.ServiceMode ? true : Configuration.DockingStation.LogToSerialPort; // always log in service mode // Determine if sequenceId passed in as argument. This is number that will be automatically // passed in as an argument to the process when Windows CE boots the device. If process // is manually started, then no sequence ID will be passed. If sequenceId is passed in, // then process MUST call SignalStarted when it feels that it's safely up and running // in order to continue with the proper boot sequence. if (args.Length > 0) { uint sequenceId = 0; try { sequenceId = UInt32.Parse(args[0]); } catch { Log.Debug("Invalid sequenceId (" + args[0] + ") found. SignalStarted not called."); } if (sequenceId > 0) { Log.Debug("SignalStarted(" + sequenceId + ")"); WinCeApi.SignalStarted(sequenceId); } } // INS-6183, 6/8/2015 - This watchdog is used in the below while-loop. The while-loop // periodically calls MonitorNetworkConnection(), which calls GetWiredNetworkAdapter(), // which calls GetNetworkAdapters(). GetNetworkAdapters() makes a call to OpenNetCF // SDF's GetAllNetworkInterfaces() to get the networking info from the OS. // Sometimes that call throws a Data Abort (unmanaged exception). Unmanaged exceptions // cannot be caught in .Net, so the exception is thrown outside and above the application, // which causes OS to display a message box informing of the Data Abort. The message box // waits for a user to press its OK button, so the thread that threw the Data Abort is // effectly hung waiting for somebody to press an OK button which is never going to happen. // The data abort may be thrown by a thread other this Master thread. But this watchdog // for the master thread should still work in that situation. This is because the // aforementioned GetNetworkAdapters has a "lock" block in it. If another thread calls // GetNetworkAdapters, it will a obtain a lock, then call into SDF's GetAllNetworkInterfaces. // If the data abort is then thrown, then GetNetworkAdapters will not have a chance to // release its lock. Then, next time master thread trys to call GetNetworkAdapters, it will // hang trying to obtain a lock, which it will never be able to do, so the watchdog timer // will eventually expire, causing a reboot, as desired. WatchDog watchDog = new WatchDog("MasterWatchDog", 60000, Log.LogToFile); // reboot if not refreshed in 60 seconds. watchDog.Start(); /////////////////////////////////////////////////////////////////////// // Used for smart card debugging. Please leave this code here for now. /////////////////////////////////////////////////////////////////////// // I2CTestThread i2cTest= new I2CTestThread(); // i2cTest.StartWork(); MonitorNetworkConnection(); Controller.LogMemoryUsage(); // Now that we've fired off the child worker threads, we have nothing more to do // except hang out and stay alive. Lower our priority and take a nap. //Thread.CurrentThread.Priority = ThreadPriority.BelowNormal; int sleepTime = 5000; int lastCheck = 0; while (true) { Thread.Sleep(sleepTime); lastCheck += sleepTime; if (lastCheck >= 300000) // 5 minutes { MonitorNetworkConnection(); //Logger.Debug( "Total Up Time: " + ( runTime / 1000 ) + " seconds" ); //Controller.LogMemoryUsage(); lastCheck = 0; } if (Controller.RunState != Controller.State.OK) { string errNum = ((int)Controller.RunState).ToString("x8"); // If a menu is active, skip the operation for now. (the only menu that should // possibly ever be active is the factory reset confirmation menu). if (!ConsoleService.IsMenuActive) { Log.Trace("SYSTEM ERROR ENCOUNTERED with error number " + errNum); if (errNum.Equals("00000001")) { ConsoleService.UpdateState(ConsoleState.ContactISCCode1011); } else if (errNum.Equals("00000002")) { ConsoleService.UpdateState(ConsoleState.ContactISCCode1012); } else if (errNum.Equals("00000004")) { ConsoleService.UpdateState(ConsoleState.ContactISCCode1014); } else if (errNum.Equals("00000008")) { ConsoleService.UpdateState(ConsoleState.ContactISCCode1018); } else if (errNum.Equals("00000010")) { ConsoleService.UpdateState(ConsoleState.ContactISCCode10110); } else { ConsoleService.UpdateState(ConsoleState.ContactISCCode10160); } } } if (lastCheck == 0 || lastCheck >= 10000) { watchDog.Refresh(); } } } // end-Run