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

Post to Twitter Post to Delicious Post to Facebook

Comments are closed.

Seek in here
Translator
Archive