Restrict Access to the Shell by Running Your Application Full Screen

Introduction

A project I had to do on the Pocket PC for a client had to be somewhat secure. For instance, if the Pocket PC had been left on the desk, it had to lock itself out after a certain period of inactivity. The solution I came up with was to make the Pocket PC go into standby mode after a given period of inactivity (even on AC) and, when the user pressed the standby button, to display a password screen. Of course, you can do whatever after the user has pressed the standby button; you could, for example, just go back to your application. I also had to restrict access to the shell. To do this, you have to make the application stay in full screen mode; this is the purpose of this article.

Making the Application Full Screen

There are various articles on how to make a dialog appear full screen. I simply use the following code to do this:

SHFullScreen( m_hWnd,  SHFS_HIDESTARTICON| SHFS_HIDETASKBAR|
                       SHFS_HIDESIPBUTTON );

MoveWindow(0,0,240,320,TRUE);

::CommandBar_Show(m_pWndEmptyCB->m_hWnd, FALSE );

This code is put into the dialog’s OnActivate method. The reason is because that, when you have gone into standby mode, the communication ports on the Pocket PC also get shut down. Thus, on coming out of standby mode, if the Pocket PC is connected to a desktop PC, ActiveSync will kick in and take the application out of full screen, thus allowing the user to access the explorer shell—not what we want.

You could disable ActiveSync if you wanted and then re-enable it if you don’t want to use a timer, but I have found that, on re-enabling ActiveSync, it doesn’t re-enable itself. Don’t ask me why; maybe it’s a bug?

The SHFullScreen removes the user’s access to the shell and gives your application full control over your screen.

MoveWindow changes the position and dimensions of the dialog. I set the width and height to 240 and 320, respectively, and positioned the dialog at the top left of the screen.

::CommandBar_Show is very important; it is used to hide or show the command bar. In this application, you hide the shell’s command bar (m_pWndEmptyCB->m_hWnd holds the handle to this).

How Do You Make the Pocket PC Go into Standby Mode?

This is very simple; the following code accomplishes it:

::keybd_event( VK_OFF,  0,  0, 0 );

This function simply synthesizes a keystroke. This is the same message that is sent when the Standby button is pressed to make the device go into standby mode. Of course, you want this to happen after a given period of inactivity. The first choice I used here was to create a thread to do this, but because this thread wouldn’t be doing much, a Windows timer was used instead (more on this later).

So, how do you detect periods of inactivity? Inactivity is when the user isn’t doing anything on the device, such as moving the mouse cursor or pressing the screen. These are messages that are sent to the dialog window in the disguise of WM_MOUSEMOVE and WM_LBUTTONDOWN. You need to capture these messages; a perfect place to do this is in the dialogs PreTranslateMessage function.

virtual BOOL PreTranslateMessage( MSG* pMsg );

You want to catch these messages before they have been dispatched. The code for this function looks like this:

BOOL CSGLockDialog::PreTranslateMessage(MSG* pMsg)
{
   switch(pMsg->message)
   {
      case WM_LBUTTONDOWN:
      case WM_MOUSEMOVE:
      m_nTimeCount = 0;
      break;
   }
   return CDialog::PreTranslateMessage(pMsg);
}

The member m_nTimeCount is used to hold the period of inactivity. You can see here that it gets set to zero when the user presses down the mouse button or moves it; you may want to add more messages here.

Repeatedly Checking for Periods of Inactivity

As mentioned previously, you need to actively keep checking for this period of inactivity. This is done within a Windows timer. Within the dialog OnInitDialog function, you set the timer:

m_nTimerID = SetTimer(1234,1000,NULL);

This just sets a timer to run every second. The timer function looks like the following:

void CSGLockDialog::OnTimer(UINT nIDEvent)
{
   //increment inactivity timer count
   m_nTimeCount ++;
   CDialog::OnTimer(nIDEvent);
   //if reached trigger level, suspend the device
   if(m_nTimeCount == 100 )
   {
      m_nTimeCount = 0;
      ::keybd_event(VK_OFF, 0, 0, 0);
   }
}

You can see here that when m_nTimeCount is equal to the hard-coded value of 100 (this is the period of inactivity in seconds; I take this from the Registry in my application, but for simplicity’s stake, I just hard code it here), you put the Pocket PC into standby mode and reset the time count back to zero.

More by Author

Must Read