Saint's Log

16Jun/100

Questioning Programming Assumptions

One of the more interesting facets of programming is probably the close relationship between a program's correctness and the set of assumptions about its execution environment and/or data. In the web world, the significance of these assumptions takes on a new height since they determine not just the correctness of the application/browser, but also how secure it is ("hackability?"). I decided to do a little test and what faster way to get em browsers running code than by bombarding em with WM_* messages. Here's a little code snippet that I wrote up for this test (warning: will blow your computer to smithereens, compile and run at your own risk):

// SendMsg.cpp : Defines the entry point for the console application.

#include "stdafx.h"
#include "windows.h"

#define START_MESSAGE WM_CLOSE
#define END_MESSAGE (START_MESSAGE + 0x0001)

int _tmain(int argc, _TCHAR* argv[])
{
  WPARAM wParam = 0;
  LPARAM lParam = 0;
  HWND hWnd = FindWindow(NULL, TEXT("Mozilla Firefox"));

  if (!hWnd) {
    MessageBox(NULL, TEXT("Could not find firefox window"), TEXT("Error"), MB_OK);
    return -1;
  }

  int errors = 0;

  for (DWORD i = 0; i < 10; i++) {
    if (!PostMessage(hWnd, START_MESSAGE, wParam, lParam)) {
      wchar_t buffer[4096];
      DWORD lasterror = GetLastError();

      FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, lasterror, 0, buffer, 4096, NULL);

      MessageBox(NULL, buffer, TEXT("Error"), MB_OK);
      errors++;
    }
  }

  if (errors)
    return -1;

  return 0;
}

The objective of this code is to send the WM_CLOSE message to a browser a given number of times (10 in this case). It starts out with a call to FindWindow to get a handle to the Firefox window. Since the window title is hard coded, a new blank tab must be active in Firefox. Once we have the handle, all that's left is to call PostMessage the desired number of times. We use GetLastError and FormatMessage for feedback if things do not proceed as planned. I settled on WM_CLOSE since its effect should be the most noticeable ;). Below are some of the results I found:

Firefox Close Boxes

Interestingly enough, the concept of getting a window handle based the window title worked well for Firefox, Opera, and IE8. It didn't work in Chrome, but I didn't want to invest the time to figure out how to get the handle there. Opera 10.53 suffers from the same problem as Firefox as pictured below (the only difference being that the browser ends up closing when one of the timeouts hits 0 so you'd better be sure you have saved all your work).

Opera Close Box

So the concept of a "Modal" dialog box seems to depend on having exactly one way to launch the box, which is definitely a questionable assumption as shown. IE8 displayed only 1 close prompt box. Kudos to them. I wonder if this type of bug effectively disappears with multiprocess browsing?

In closing, I should note that I also tried the WM_QUIT message (only 1 of which is necessary). Firefox just died as did just about everything else on my system, including explorer.exe and all the other EXEs unfortunate enough to have been running at the time (I was doing some mass message posting initially and it was only after losing a bunch of data that I decided it was in my best interest to post these messages to a specific window).

For anyone interested in running this program, note that Opera 10.53 will CRASH if you send it WM_QUIT! Crash report explains that "Opera.exe 3374 caused exception C0000005 at address 677DD1F3 (Base: 1250000)." I've sent in a crash report so that should hopefully get fixed soon. This shouldn't affect web content since it can't pull these PostMessage stunts.

Note that this program is easily modified to automate the sending of a range of messages by changing to loop limits to [START_MESSAGE, END_MESSAGE]. I will hopefully have enough time to build a full blown GUI tool for this.