Introduction
BSOD is an error message that is displayed when a critical system error occurs.
From Wikipedia: “The Blue Screen of Death (also known as a stop error, BSoD, bluescreen, or Blue Screen of Doom) is a colloquialism used for the error screen displayed by some operating systems, most notably Microsoft Windows, after encountering a critical system error that can cause the system to shut down to prevent irreversible damage to the system's integrity. It serves to present information for diagnostic purposes that were collected as the operating system issued a bug check.”
Before Windows XP, appearing of BSOD was frequent. If one of the running applications did something wrong, and you were welcomed by BSOD! Since Windows XP, it’s not so frequent, or I can say, it's rare, but still the blue color of screen makes people pale or red!
Background
Often infamous things from history are used to create fun. The same is the case with BSOD. Sometime back, I encountered a screensaver application from sysinternals.com.
This is a screensaver application which simulates BSOD along with the restarting of PC. As the source code was not available, I created a new application with the same behavior. This application also provides details on how to create a screen saver application with MFC. It can be run both as a screen saver and standalone application based on the arguments.
BSOD Internals
Whenever the Windows operating system encounters a system crash (due to some application error or by some other reason), the BSOD screen appears and shows the error message. Due to the system crash, the screen resolution is changed to a 640X480 and a text message is displayed with white text in blue background.
A typical BSOD image can be obtained from Google image search.
The font used while showing this message is Lucida Console (Notepad Font). I found this information by printing message with different fonts and comparing it with BSOD screen. Later, I discovered that this information is already mentioned in Wikipedia J.
Simulating BSOD
From the above gathered information, we can simulate a BSOD by:
- Changing screen resolution to 640x480.
- Showing text message with font as Lucida Console, and background color as blue.
If this work is done in a screen saver application, we get a BSOD screen saver.
Simulating PC Restart
This article talks about simulating only Windows XP restart. For other versions of windows, changes need to be done in the application.
When we boot a Windows XP based PC, after the POST process, Windows logo with a special progress bar is displayed at a resolution of 640x480. In the background, the drivers are loaded and when the loading is done, Explorer.exe is launched which loads the desktop. This is just an overview and many other important tasks are done behind the curtain. To know more, click here.
If we can somehow show the same logo with the same progressbar in a 640x480 resolution window, we can simulate PC start process. To get the real Logo & ProgressBar, I used PrintScreen during the Boot Process of WindowsXP on a virtual machine (Virtual box). I extracted the scrollbar thumb image and added some motion in it to simulate progressbar.
Final Application Approach
- A MFC dialog based application is created using the wizard. The dialog is borderless and it’s hidden from the appearing in the taskbar.
- The Windows logo is saved as a resource file and shown in picture viewer control.
- The default BSOD Error message is stored in the program as a
string
. To provide flexibility to change message on the fly, it’s also read from ErrorMessage.txt file from application directory. The default message will be displayed only if the ErrorMessage.txt file is not available in the app path.
- A class
CProgressBar
is created to draw the custom scrollbar control. This class loads the scroll thumb from resource and scrolls it based on timer event.
- During the initialization of controls, the application saves the current resolution and changes the resolution to 640X480. To change resolution, I have reused the code from CodeProject article - Programmatically change display resolution By Cristian Amarie.
- The application displays the BSOD message and visualizes PC Restart in a loop. This loop is maintained by another timer. The duration of Error Message, Windows startup & Post Start duration can be controlled by modifying
m_ErrorMsgDuration
, m_WindowStartDuration
& m_AfterStartDuration
variable values respectively.
Application as Screen Saver
To run the application as screensaver, change the extension from exe to scr and copy it in c:\Windows\System32 folder. Now it can be configured using the Screen Saver settings dialog.
Screen Saver Details
A screen saver is an application which runs in full screen mode with its window at topmost position. The screen saver application has extension scr in place of exe. To install a screensaver, the executable can be manually copied to windows\system32 folder or the user can choose the Install option from right click context menu.
A screensaver is launched by Windows with one of three command line options:
/s – This option is passed to start the screensaver in full-screen mode. In this case, the application is launched normally to show the output in full screen.
/c – This option is passed to show the configuration settings dialog box. In this case, the application shows a configuration dialog to modify the launch time and other settings.
/p #### – This option is passed to display the preview of the screensaver using the specified window handle ####. The value passed with /p is the decimal equivalent of preview window handle in the screen saver settings dialog. With this option, the application is expected to run in the background and use this window as render window. In this case, the output of application should be displayed in the window whose handle is passed while launching application.
In place of directly rendering in the preview window, screen savers generally create a new window with the preview window as parent window. The new window position and size is kept the same as the preview window and the application renders its output in the new window. As the new window size & position is the same as the preview window, it looks as if the output is displayed in the preview window.
For simplicity, I have skipped the preview mode code from the BSOD application. Lucian Wischik has a complete website having details for creating screen saver with all the options working. You can visit his site for more details.
About the Code
The code for this article is very simple. The approach of this application is already described above and the code is written to follow that approach.
Following is the class list in this project:
CBsodSaverApp
: Main application class derived from CWinApp
CBsodSaverDlg
: Main dialog class derived from CDialog
CChangeRes
: Class used to change screen resolution
CConfigDlg
: Dialog class for changing the application settings
CMyStatic
: Class for setting background and foreground color of a static
control.
CProgressBar
: Class which simulates the Windows startup progress bar.
At the time of application start, its parameters are checked in function CBsodSaverApp::InitInstance()
and either the Config Dialog or the main application dialog is displayed based on the provided parameters.
CString strOption = CmdLine.Right (CmdLine.GetLength() - CmdLine.ReverseFind('/') - 1);
switch(strOption[0])
{
case 'c':
case 'C':
{
CConfigDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
}
break;
case 'p':
case 'P':
{
}
break;
case 's':
case 'S':
default: {
CBsodSaverDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
}
}
The CBsodSaverDlg
class contains the following member variables:
CMyStatic m_BlueText; CBrush m_BkgrndBrush; COLORREF m_BkColor; CStatic m_WindowsLogo; CProgressBar m_ScrollbarBox; CPoint m_OldResolution; int m_TimerCount; CString m_ErrorMessage; UINT m_ErrorMsgDuration; UINT m_WindowStartDuration; UINT m_AfterStartDuration;
A timer is started in the OnInitDialog()
function and the UI objects are made hidden/visible based on m_ErrorMsgDuration
, m_WindowStartDuration
and m_AfterStartDuration
values.
The function RepositionControls()
is used to reposition the controls in the proper position.
The class CProgressBar
maintains its own timer to reposition the scrollbar thumb image in a given rectangle area. The width, height & speed are maintained by macros:
#define SCROLL_BAR_HEIGHT 9
#define SCROLLING_SPEED 40
Points of Interest
As told above, in the preview mode, the screen saver is launched with the preview window handle as its 2nd argument. The handle is passed as decimal argument and the screen saver application uses this handle as render window.
That means that if a window handle is passed with /p
argument to the screen saver, it will render to that window only. To verify this, start the Notepad application and get its main window handle with SPY++ application that is shipped with Visual Studio. Use calculator to convert window handle value from Hex to decimal.
On my machine, the Notepad window handle is – 000F05F6 and its Decimal equivalent is 984566. Now to launch screen saver, open command prompt and go to c:\windows\System32 folder. Use dir
command to search for the available screen savers. I am using Windows 7 and have Bubbles screen saver.
To launch the bubbles screen saver in Notepad, run the command like this:
c:\Windows\System32>Bubbles.scr /p 984566
And wow!!!
The screen saver is running in Notepad.
I am also trying to develop a real BSOD application which will cause the system everytime user runs that. If someone has some ideas, kindly share that.
History