Exercise 2: Solving UIPI Issues

Task 1 - Explore the Ping Pong Sample

In this task, you will investigate the Visual Studio solution to understand what the code does.

  1. Double-click the PingPongBroken solution.

    Note:
    Help

    Visual Studio 2008 should start and load the solution. The solution contains four projects: two native and two managed. Each pair is the Ping Pong application itself and a convenient loader that starts one process with standard user privileges and the other with administrator privileges.

  2. Right-click the PingPongForm.cs or PingPongForm.vb file and select View Code.
  3. Scroll down to the NativeWrappers class.

    Note:
    Help

    This internal class wraps some native functions for message registration and message passing. The PingPongFrom constructor registered the special message by calling the RegisterWindowsMessage function, to obtain a global (technically, globally to the process’ Windows Station) message id for inter-process communication. The resulting message, _message, is the one posted between windows of the two running processes.

  4. An override of the WindowProc method in the PingPongForm class handles the registered message and uses a timer to alternately display the message parts with 500 msec intervals.
  5. The Main method searches for another instance of the same executable by looking for the existence of another window with the same caption (using a P/Invoke around the FindWindow function).

Task 2 - Fix the Code

The PostMessage function used for message passing fails if its intended message is to a window belonging to a process with a higher privilege level. However, we can use a message filter to let some messages through:

  1. Add a P/Invoke wrapper around the ChangeWindowMessageFilter native function, which can filter messages regardless of privilege levels.
  2. Add the following code In the NativeWrappers class:public enum ChangeWindowMessageFilterFlags : uint {
    Add = 1, Remove = 2
    };

    [DllImport("user32")]
    public static extern bool ChangeWindowMessageFilter(uint msg,
    ChangeWindowMessageFilterFlags flags);
Public Enum ChangeWindowMessageFilterFlags As UInteger
Add = 1
Remove = 2
End Enum
<DllImport("user32")> _
Public Shared Function ChangeWindowMessageFilter(ByVal msg As UInteger, ByVal flags As ChangeWindowMessageFilterFlags) As Boolean
End Function

Note:
Help

After the message registers in the form’s constructor and before the first message posts, use the newly added wrapper to let the registered message pass through, regardless of privilege levels:

  1. Add a call to NativeWrappers.ChangeWindowMessageFilter with the flag ChangeWindowMessageFilterFlags.Add:_message = NativeWrappers.RegisterWindowMessage("BALL");
    if(_message == 0)
    Close();
    else {
    NativeWrappers.ChangeWindowMessageFilter(_message,
    NativeWrappers.ChangeWindowMessageFilterFlags.Add);
    NativeWrappers.PostMessage(Program.hOtherForm, _message, Handle,
    IntPtr.Zero);
    }
_message = NativeWrappers.RegisterWindowMessage("BALL")
If _message = 0 Then
Close()
Else
NativeWrappers.ChangeWindowMessageFilter(_message,
NativeWrappers.ChangeWindowMessageFilterFlags.Add)
NativeWrappers.PostMessage(Program.hOtherForm, _message, Handle,
IntPtr.Zero)
End If

  1. Build the project and test it with ManagedPingPongLoader.exe. It should work as expected. The complete solution is in the PingPongFixed folder.