Warm reboot of a PocketPC/CE
To be able to reset a PocketPC/WindowsCE programmatically from within a managed application, it is necessary to send a IOCTL to the device using KernelIoControl. This API is not available directly in managed code, so we need to P/Invoke KernelIoControl, providing it with the correct IOCTL (IOCTL_HAL_REBOOT). To assure that IOCTL’s are unique, they can be created in native code using the CTL_CODE macro. To be able to create the same IOCTL from managed code, we make sure to define the IOCTL in a similar way as CTL_CODE does. Note that running the sample code from inside any Visual Studio 2003 or up resets the device, resulting in a lost connection to the device.
Code:
Complete C# sample. A Windows Form PocketPC application containing a button to reset the device:
namespace ResetDevice { using System; using System.Drawing; using System.Collections; using System.Windows.Forms; using System.Data; using System.Runtime.InteropServices; public class Form1 : System.Windows.Forms.Form { private System.Windows.Forms.Button button1; private System.Windows.Forms.MainMenu mainMenu1; internal static Int32 METHOD_BUFFERED = 0; internal static Int32 FILE_ANY_ACCESS = 0; internal static Int32 FILE_DEVICE_HAL = 0x00000101; internal static Int32 IOCTL_HAL_REBOOT = ((FILE_DEVICE_HAL) < < 16) ((FILE_ANY_ACCESS) < < 14) ((15) < < 2) (METHOD_BUFFERED); [DllImport("coredll.dll", SetLastError=true)] private static extern bool KernelIoControl(Int32 dwIoControlCode, IntPtr lpInBuf, Int32 nInBufSize, byte[] lpOutBuf, Int32 nOutBufSize, ref Int32 lpBytesReturned); public static void ResetDevice() { int cb = 0; byte[] buffer = new byte[1]; KernelIoControl(IOCTL_HAL_REBOOT, IntPtr.Zero, 0, buffer, 0, ref cb); } public Form1() { InitializeComponent(); } protected override void Dispose( bool disposing ) { base.Dispose( disposing ); } private void InitializeComponent() { this.mainMenu1 = new System.Windows.Forms.MainMenu(); this.button1 = new System.Windows.Forms.Button(); this.button1.Location = new System.Drawing.Point(64, 144); this.button1.Size = new System.Drawing.Size(112, 48); this.button1.Text = "Reset Device"; this.button1.Click += new System.EventHandler(this.button1_Click); this.Controls.Add(this.button1); this.Menu = this.mainMenu1; this.Text = "Form1"; } static void Main() { Application.Run(new Form1()); } private void button1_Click(object sender, System.EventArgs e) { ResetDevice(); } } } Definition of the IOCTL, P/Invoke declaration to KernelIoControl and invocation of the IOCTL in VB.NET: Imports System.Runtime.InteropServices Public Class Form1 Inherits System.Windows.Forms.Form Friend WithEvents Button1 As System.Windows.Forms.Button Friend WithEvents MainMenu1 As System.Windows.Forms.MainMenu Private Shared METHOD_BUFFERED As Int32 = 0 Private Shared FILE_ANY_ACCESS As Int32 = 0 Private Shared FILE_DEVICE_HAL As Int32 = &H101 Private Shared IOCTL_HAL_REBOOT As Int32 = (&H10000 * FILE_DEVICE_HAL) Or _ (&H4000 * FILE_ANY_ACCESS) Or _ (&H4 * 15) Or METHOD_BUFFERED Declare Function KernelIoControl _ Lib "CoreDll.dll" (ByVal dwIoControlCode As Int32, _ ByVal lpInBuf As IntPtr, _ ByVal nInBufSize As Int32, _ ByVal lpOutBuf() As Byte, _ ByVal nOutBufSize As Int32, _ ByRef lpBytesReturned As Int32) As Boolean ' Generated code, omitted in this example Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click Dim outbuff(1) As Byte Dim dwOutBytes As Int32 = 0 If Not KernelIoControl(IOCTL_HAL_REBOOT, _ IntPtr.Zero, _ 0, outbuff, 0, dwOutBytes) Then MessageBox.Show("KernelIoControl failed") End If End Sub End Class

