QA: How can I soft reset Pocket PC device?
October 28th, 2004 by Andrey Yatsyk

QA updated October 7, 2005

Question

How can I soft reset Pocket PC device from my embedded Visual C++ program?

Answer

This QA shows how to soft reset Windows Mobile device. I will use different approaches according to operating system version. It is possible to soft reset a device by:
Invoking KernelIoControl with IOCTL_HAL_REBOOT control code. This approach was used in previous edition of this article but it has a number of disadvantages (implementing of this function is not required for OEMs and some old Pocket PC devices really miss this functionality, this function usually restricted so it could be used only in privileged mode – now this is an issue only for Smartphones but not for Pocket PC and finally but most important buffers is not flushed so user could lost his data)
By SetSystemPowerState
And recommended way is to use a function ExitWindowsEx
First method is available on all up-to-date Pocket PC devices. Second one is available on devices with operating system version starting from Windows Mobile 2003. And third one is available on Windows Mobile 5.0 and above.
I have tried to write a code that could use best approach for available platform depending on operating system version.

#include <winioctl.h>

void SoftReset();

extern "C" __declspec(dllimport) BOOL KernelIoControl(DWORD dwIoControlCode, LPVOID lpInBuf, DWORD nInBufSize, LPVOID lpOutBuf, DWORD nOutBufSize, LPDWORD lpBytesReturned);

static void ResetWithExitWindows()
{
HMODULE hModule = ::LoadLibrary(TEXT("aygshell.dll"));

typedef BOOL (*ExitWindowsExFunction)(UINT uFlags, DWORD dwReserved);

ExitWindowsExFunction f = (ExitWindowsExFunction)::GetProcAddress(hModule, TEXT("ExitWindowsEx"));

#ifndef EWX_REBOOT
#define EWX_REBOOT 2
#endif

f(EWX_REBOOT, 0);

FreeLibrary(hModule);

}

static void ResetWithSetSystemPowerState()
{
typedef DWORD (*SetSystemPowerStateFunction)(LPCWSTR pwsSystemState, DWORD StateFlags, DWORD Options);
HMODULE hModule = ::LoadLibrary(TEXT("Coredll.dll"));

SetSystemPowerStateFunction f = (SetSystemPowerStateFunction)
::GetProcAddress(hModule, TEXT("SetSystemPowerState"));

#ifndef POWER_STATE_RESET
#define POWER_STATE_RESET DWORD(0x00800000)
#endif

f(NULL, POWER_STATE_RESET, 0);
::FreeLibrary(hModule);
}

static void ResetWithKernelIoControl()
{
#ifndef IOCTL_HAL_REBOOT
#define IOCTL_HAL_REBOOT CTL_CODE(FILE_DEVICE_HAL, 15, METHOD_BUFFERED, FILE_ANY_ACCESS)
#endif

KernelIoControl(IOCTL_HAL_REBOOT, NULL, 0, NULL, 0, NULL);
}

void SoftReset()
{
OSVERSIONINFO vi;
memset(&vi, 0, sizeof(vi));
vi.dwOSVersionInfoSize = sizeof(vi);
VERIFY(GetVersionEx(&vi));
if (vi.dwMajorVersion >= 5) {
ResetWithExitWindows();
} else if (vi.dwMajorVersion==4 && vi.dwMinorVersion>=20) {
ResetWithSetSystemPowerState();
} else {
ResetWithKernelIoControl();
}
}

Related resources:

Section: Power
QA: How to suspend Pocket PC device?
QA: How to perform hard reset?
Article: Turn Off the Display While Running Applications
Article: Turn the device power off in eVB
Article: Power Notification

(Discuss in forum)

Leave a Reply