-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathProgram.cs
More file actions
656 lines (623 loc) · 29.4 KB
/
Program.cs
File metadata and controls
656 lines (623 loc) · 29.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
/*
* Blue screen simulator plus
* Codename: LotsaSpaghetti
*
* Version 3.1 (pre-release)
*
* {} markus' software // {} markuse tarkvara
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing.Text;
using System.IO;
using System.Linq;
using System.Net.NetworkInformation;
using System.Threading;
using System.Windows.Forms;
using Microsoft.Win32;
using SimulatorDatabase;
using UltimateBlueScreenSimulator.Forms.Legacy;
namespace UltimateBlueScreenSimulator
{
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
//Form creation
public static NewUI F1 { get; set; }
public static Main F2 { get; set; }
public static Splash spl;
public static DrawRoutines dr;
public static GlobalSettings gs = new GlobalSettings();
public static bool loadfinished = true;
//AppData directory
public readonly static string prefix = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\Blue Screen Simulator Plus\";
//Command line syntax
public static string[] cmds = new string[]
{
"/? - Displays command line syntax",
"/wv xx - Set a specific configuration/os (e.g. \"XP\", spaces require the value to be surrounded with double quotes)",
"/h - Doesn't show main GUI. If no simulation is started or the simulation is finished, the program will close.",
"/hwm - Hides watermark",
"/c - Simulates a system crash",
"/config xx - Loads a configuration file (xx is the file name, if there are spaces, you must use double quotes)",
"",
"/ddesc - Disables error descriptions",
"/dqr - Disables QR code on Windows 10/11 crash screen",
"/srv - Displays Windows Server bugcheck when wv is set to 10 or 11",
"/dac - Disables autoclose feature (Modern blue screens only)",
"/gs - Displays green screen when wv is set to 10",
"/ap - Displays ACPI blue screen (Windows Vista/7 only)",
"/win - Enables windowed mode",
"/random - Randomizes the crash screen (does NOT randomize any custom attributes set)",
"",
"/desc - Forcibly enable error description",
"/ac - Forcibly enable autoclose feature",
"/dap - Forcibly disable ACPI error screen (Windows Vista/7)",
"/damd - Forcibly display \"GenuineIntel\" on Windows NT blue screen",
"/dblink - Forcibly disable blinking cursor on Windows NT blue screen",
"/dgs - Forcibly disable green screen on Windows 10 blue screen",
"/qr - Forcibly enable QR code on Windows 10 blue screen",
"/dsrv - Forcibly disable server blue screen when version is set to Windows 10",
"/stack - Forcible enable stack trace on Windows NT blue screen",
"/dfile - Forcible disables potential culprit file",
"/ctd - Forcibly enables countdown",
"",
"/clr - Clears the verification certificate from this computer, causing the first use message to pop up.",
"/hidesplash - Hides the splash screen",
"/legacy - Starts the program with Legacy UI"
};
internal static bool verificate = false;
public static int load_progress = 100;
public static string load_message = "Initializing...";
public static bool hidden = false;
internal static string[] changelog = new string[]
{
"* Renamed Windows 11 Beta to Windows 11",
"* Renamed Windows 11 to Legacy Windows 11",
"- Verifile checks when previewing or changing settings for a screensaver (pointless)",
};
public static bool hide_splash = false;
public static bool force_legacy = false;
public static bool halt = false;
// initialize global objects
public static Verifile verifile;
public static Thread splt;
public static CLIProcessor clip;
public static TemplateRegistry templates;
public readonly static byte[] footerBytes = new byte[] { 0x42, 0x33, 0x65, 0x72 };
public static string[] validnames = new string[]
{
"blue screen simulator plus",
"bssp",
"ultimatebluescreensimulator",
"blue.screen.simulator.plus"
};
public static bool isScreensaver = Process.GetCurrentProcess().MainModule.ModuleName.ToLower().EndsWith(".scr");
public static RegistryKey wineKey = Registry.LocalMachine.OpenSubKey(@"Software\Wine", false);
public readonly static string[] tips =
{
"Material Design is a design language developed by Google in 2014!",
"You can close a bugcheck by pressing ALT+F4",
"There is a crash screen for a program that simulates crash screens, right?",
"The codename for version 2.0 came from a song that was playing in the background during the development process",
"If Microsoft decides to change their error screens, I'll push an update that adds these changes",
"Configuration files store every property about all error screens",
"Windows Vista/7 blue screen scrolls, when there is too much information on screen",
"There are rainbow easter eggs for Windows XP, Vista, 7, CE, and 1.x/2.x blue screens",
"In prank mode, the watermark on a bugcheck is disabled automatically",
"There are three error screens in this program, that technically aren't blue screens",
"This program, for the most part, also works in ReactOS, which is an open source Windows clone based on reverse engineering",
"The first Windows XP bluescreen I ever saw displayed DRIVER_IRQL_NOT_LESS_OR_EQUAL as the error code",
"You can also use the Enter key to close Windows 9x bluescreens",
"Microsoft originally planned to replace a blue screen with a black one as early as Windows 8",
"Every major Windows release, up until later builds of Windows 11, has had some sort of a blue screen",
"Blue is a color that symbolises peace",
"Windows 2000 blue screen didn't use rasterized fonts in previous versions, because I figured it looked 'close enough' to the original",
"If you use the 'choose' button when setting a culprit file, you might see some weird filenames...",
"The background of the logo graphic in the about screen displays two major colors used by bugcheck screens - black and blue",
"This program isn't a copy of FlyTech's work, instead it was developed from scratch, because of the limitations I saw when trying out FlyTech's blue screen simulator.",
"You can use progress tuner to make more realistic progress indicators for modern bugchecks",
"There is no random factoid here",
"The splash screen crashes were really annoying to debug when building version 3.1, because they would only occur occasionally",
"I actually used a super ultrawide monitor for testing this version of BSSP",
"Is this the last version? Yesn't!",
"Liftoff, we have liftoff!",
"Every major version of BSSP (1.x, 2.x, 3.x) has its own save file format. There are rumors that the next simulator will use XML as the save format.",
"We got Blue Screen Simulator Plus 3.1 before GTA VI",
"I hope she made lotsa spaghetti!",
"öӧӧöӧӧӧӧӧӧӧӧӧӧӧöӧӧӧöӧöӧööӧӧӧӧӧöӧӧöӧӧӧöӧӧöö ӧöööӧööӧö ӧöӧӧӧӧöӧöӧӧöӧöӧӧ öӧӧöӧӧӧöӧӧӧöӧööӧöӧööӧöӧӧӧöӧӧöӧӧӧöӧӧöö öӧööӧöööӧööööӧöӧӧӧӧöӧöӧӧӧöö",
"This simulator gives Microsoft and Crowdstrike PTSD without actually crashing computers",
"KERNEL PANIC!\n\nPlease reboot your computer.\n\nAttempted to kill init! exitcode=0x0000000b",
"\"That's what I get for working at Microsoft\"\n - Gabe Newell",
"Your computer was restarted because of a problem.\n\nClick Report to see more detailed information and send a report to Apple.",
"There's truth, lies and statistics....",
"There is a chance you saw this factoid already",
$"The lucky number for this session is {BlueScreen.r.Next(0,9999)}",
"In a 2014 presentation, Microsoft discussed the name for the next version of Windows, which they originally wanted to call Windows One, but instead decided to go for Windows 10, because the giants before them already made Windows 1.0.",
"I'm everyone. I'm everywhere. I see everything. I hear everybody.",
"There is no escape.",
"1 + 1 = 10 (at least that's what computers think)",
"Windows 8 and later crash screens have a text pop-in effect, which makes them look more authentic!",
"Please stop clicking the \"Random factoid\" button!",
"target: void"
};
[STAThread]
public static int Main(string[] args)
{
try
{
gs.Log("Info", "Checking fonts");
// Process CLI args
clip = new CLIProcessor(args);
if (!clip.CheckNoSplash() && CheckFonts().Length > 0)
{
switch (MessageBox.Show("The following fonts must be installed before you can use this program:\n\n" + string.Join("\n", CheckFonts()),
"Cannot start this program", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Error))
{
case DialogResult.Abort:
return 95;
case DialogResult.Retry:
Application.Restart();
return 0;
case DialogResult.Ignore:
break;
}
}
//Application initialization
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
if (AttachmentReader(args))
{
return 0;
}
//If hidesplash flag is not set, display the splash screen
hide_splash = clip.CheckNoSplash();
if (!hide_splash)
{
hidden = true;
splt = new Thread(ShowLoading);
splt.Start();
if (clip.CheckPreviewSplash())
{
halt = true;
}
}
if (isScreensaver && !args.Contains("/s") && !args.Contains("/S"))
{
verificate = true;
} else
{
verifile = new Verifile();
verificate = verifile.Verify;
}
gs.Log("Info", "Verifile passed");
// this delay makes sure that the splash screen is actually displayed
Thread.Sleep(100);
gs.Log("Info", "Initializing configurations list");
templates = new TemplateRegistry();
gs.Log("Info", "Initializing draw routines");
dr = new DrawRoutines();
//Initialize forms
gs.Log("Info", "Creating initial form");
F1 = new NewUI();
//Set default selection indexes for combo boxes
F1.windowVersion.SelectedIndex = 0;
F1.comboBox2.SelectedIndex = 0;
clip.ProcessArgs();
if (halt)
{
return 0;
}
//Load application configuration if it exists
try
{
gs = gs.LoadSettings();
bool missingFonts = !gs.LegacyUI && (CheckFonts(true).Length > 0);
if (missingFonts)
{
clip.ExitSplash();
}
if (missingFonts && (MessageBox.Show("The following optional fonts used by this program were not found:\n\n" + string.Join("\n", CheckFonts(true)) + "\n\nYou can proceed without installing these fonts, however some UI elements may not look right. Do you still want to start this program?", "Notice", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.No))
{
Application.Exit();
return 0;
}
if (gs.LegacyUI)
{
F2 = new Main();
}
if (wineKey != null)
{
gs.Log("Warning", "Wine registry key detected - the user may have launched this program in Linux or macOS. This may cause unexpected glitches!");
if (!gs.LegacyUI)
{
gs.Log("Warning", "Material UI is not available when application is launched through Wine");
gs.LegacyUI = true;
}
}
}
catch (Exception ex) when (!Debugger.IsAttached)
{
DisplayMetaError(ex, "VioletScreen");
}
if (gs.Autosave && File.Exists(prefix + "bluescreens.json"))
{
templates = templates.LoadConfig(prefix + "bluescreens.json");
}
//Load Windows NT error codes from the database
gs.Log("Info", $"Initializing NT error code database");
ReloadNTErrors();
gs.Log("Info", "Initializing 9x error code database");
ReloadNxErrors();
//run application
if (gs.LegacyUI || force_legacy)
{
Application.Run(F2);
}
else
{
Application.Run(F1);
}
return gs.ErrorCode;
}
catch (Exception e) when (!Debugger.IsAttached)
{
MessageBox.Show($"Runtime error.\r\n{e.Message}\r\n{e.StackTrace}", "Blue screen simulator plus", MessageBoxButtons.OK, MessageBoxIcon.Error);
return 300;
}
}
/// <summary>
/// Displays the splash screen
/// </summary>
public static void ShowLoading()
{
try
{
spl = new Splash
{
args = clip.args
};
spl.ShowDialog();
} catch (ThreadAbortException)
{
Thread.ResetAbort();
return;
}
}
/// <summary>
/// Reloads NT error codes on the main form
/// </summary>
public static void ReloadNTErrors()
{
F1.comboBox1.Items.Clear();
if (gs.LegacyUI)
{
F2.comboBox1.Items.Clear();
}
try
{
foreach (string element in templates.NtErrors)
{
string[] codesplit = element.Split('\t');
string final = codesplit[1].ToString() + " (" + codesplit[0].ToString() + ")";
F1.comboBox1.Items.Add(final);
if (gs.LegacyUI)
{
F2.comboBox1.Items.Add(final);
}
}
F1.comboBox1.SelectedIndex = 9;
if (gs.LegacyUI)
{
F2.comboBox1.SelectedIndex = 9;
}
}
catch
{
gs.ErrorCode = 20;
}
}
public static void ReloadNxErrors()
{
F1.nineXErrorCode.Items.Clear();
if (gs.LegacyUI)
{
F2.nineXErrorCode.Items.Clear();
}
try
{
foreach (string element in templates.NxErrors)
{
string[] codesplit = element.Split('\t');
string final = codesplit[0].ToString() + ": " + codesplit[1].ToString();
F1.nineXErrorCode.Items.Add(final);
if (gs.LegacyUI)
{
F2.nineXErrorCode.Items.Add(final);
}
}
F1.nineXErrorCode.SelectedIndex = 9;
if (gs.LegacyUI)
{
F2.nineXErrorCode.SelectedIndex = 9;
}
} catch
{
gs.ErrorCode = 20;
}
}
/// <summary>
/// Displays an error message about missing DLL files
/// </summary>
public static void DllError()
{
MessageBox.Show("Required DLL files are missing. To use the save and load feature, all DLLs must be present in the application's working directory.", "DLL error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
private static string[] CheckFonts(bool optionalFonts = false)
{
using (InstalledFontCollection fontsCollection = new InstalledFontCollection())
{
System.Drawing.FontFamily[] fontFamilies = fontsCollection.Families;
List<string> fonts = new List<string>();
foreach (System.Drawing.FontFamily font in fontFamilies)
{
fonts.Add(font.Name);
}
List<string> missing_fonts = new List<string>();
foreach (string font in (optionalFonts ? Properties.Resources.optionalFonts : Properties.Resources.fonts).Split(';'))
{
if (!fonts.Contains(font))
{
missing_fonts.Add(font);
}
}
return missing_fonts.ToArray();
}
}
/// <summary>
/// Displays a meta-error
/// </summary>
/// <param name="ex">Caught exception</param>
/// <param name="type">Error type (e.g. VioletScreen)</param>
private static void DisplayMetaError(Exception ex, string type)
{
gs.Log("Critical", $"{type} exception: {ex.Message}\n{ex.StackTrace}");
Metaerror me = new Metaerror()
{
ex = ex,
type = type
};
if (gs.EnableEggs)
{
switch (me.ShowDialog())
{
case DialogResult.Abort:
return;
case DialogResult.Retry:
Application.Restart();
return;
case DialogResult.Ignore:
break;
}
}
else { MessageBox.Show("There was a problem with the settings file.\n\n" + ex.Message + "\n\n" + ex.StackTrace, "E R R O R", MessageBoxButtons.OK, MessageBoxIcon.Error); }
}
/// <summary>
/// Checks for internet connectivity
/// </summary>
/// <param name="minimumSpeed">Minimum speed to be considered connected</param>
/// <returns>Returns true if connected</returns>
public static bool DoWeHaveInternet(long minimumSpeed)
{
if (!NetworkInterface.GetIsNetworkAvailable())
{
return false;
}
foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
{
// discard because of standard reasons
if ((ni.OperationalStatus != OperationalStatus.Up) ||
(ni.NetworkInterfaceType == NetworkInterfaceType.Loopback) ||
(ni.NetworkInterfaceType == NetworkInterfaceType.Tunnel))
{
continue;
}
// this allow to filter modems, serial, etc.
// I use 10000000 as a minimum speed for most cases
if (ni.Speed < minimumSpeed)
{
continue;
}
// discard virtual cards (virtual box, virtual pc, etc.)
if ((ni.Description.IndexOf("virtual", StringComparison.OrdinalIgnoreCase) >= 0) ||
(ni.Name.IndexOf("virtual", StringComparison.OrdinalIgnoreCase) >= 0))
{
continue;
}
// discard "Microsoft Loopback Adapter", it will not show as NetworkInterfaceType.Loopback but as Ethernet Card.
if (ni.Description.Equals("Microsoft Loopback Adapter", StringComparison.OrdinalIgnoreCase))
{
continue;
}
return true;
}
return false;
}
/// <summary>
/// Allows you to test if invalid characters exist within a configuration
/// </summary>
/// <param name="letters">Character set</param>
/// <param name="me">Configuration template</param>
/// <returns>true when errors are found</returns>
public static bool TestDicts(string[] letters, BlueScreen me)
{
bool errors = TestDict(letters, me.GetTexts().Values.ToArray()) || TestDict(letters, me.GetTitles().Values.ToArray());
if (errors)
{
loadfinished = true;
MessageBox.Show("Disallowed characters found! Only the following characters are allowed:\n" + string.Join("", letters), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
return errors;
}
private static bool TestDict(string[] letters, string[] strings)
{
bool errors = false;
foreach (string text in strings)
{
string replacedText = text;
foreach (string c in letters)
{
replacedText = replacedText.Replace(c, "");
}
if (replacedText.Replace("\r", "").Replace("\n", "").Replace("{", "").Replace("}", "") != "")
{
errors = true;
}
}
return errors;
}
/// <summary>
/// For self-contained simulator support. Loads a JSON string from the end of executable into memory if the special B3er header is found, then displays a crash screen based on those settings.
/// </summary>
/// <returns>If the header is found, returns true</returns>
private static bool AttachmentReader(string[] args)
{
// if we are just using the main program and not a self contained one, just return false
// trying to load a non-existant footer will increase load times for no good reason
foreach (string entry in validnames)
{
if (System.Diagnostics.Process.GetCurrentProcess().MainModule.ModuleName.ToLower() == $"{entry}.exe")
{
return false;
}
}
string jsondata = GetEmbedded();
if (jsondata != "")
{
gs = gs.LoadSettings();
clip = new CLIProcessor(new string[] { "/hidesplash" });
if (isScreensaver && !args.Contains("/s") && !args.Contains("/S"))
{
verificate = true;
}
else
{
verifile = new Verifile();
verificate = verifile.Verify;
}
if (verificate || args.Contains("/p"))
{
templates = new TemplateRegistry();
dr = new DrawRoutines();
F1 = new NewUI();
Thread th = new Thread(new ThreadStart(() => {
// initialize BlueScreen object
UIActions.me = templates.LoadSingleConfig(jsondata);
if (isScreensaver)
{
if ((!args.Contains("/s") && !args.Contains("/S") && !args.Contains("/p")) || args.Contains("/c"))
{
UIActions.me = templates.LoadSingleConfig(jsondata);
Application.Run(new ScreenSaverConfig());
return;
}
else if (string.Join(" ", args).Contains("/p"))
{
if (!string.Join(" ", args).Contains(":") && args.Length < 2)
{
MessageBox.Show("Window handle was not provided!", "Blue Screen Simulator Plus", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
string ProcessID = args.Length < 2 ? string.Join(" ", args).Split(':')[1] : args[1];
IntPtr previewWndHandle = new IntPtr(long.Parse(args[1]));
Application.Run(new Forms.Loaders.ScreensaverPreview(previewWndHandle));
return;
}
}
// display the crash screen
UIActions.me.Show();
}));
th.Start();
th.Join();
}
} else
{
MessageBox.Show($"Invalid footer data or filename. Please rename the executable back or delete it.\r\n\r\nValid names include the following:\r\n{string.Join("\r\n", validnames)}", "Special footer missing", MessageBoxButtons.OK, MessageBoxIcon.Error);
return true;
}
return true;
}
/// <summary>
/// Obtain embedded configuration within the running program (embed to executable option)
/// </summary>
/// <param name="appname">Path to exe (optional, defaults to current app)</param>
/// <returns>Embedded settings JSON data as string</returns>
public static string GetEmbedded(string appname = null)
{
List<byte> data = new List<byte>();
string filename = appname ?? System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
string tempname = Path.GetTempPath() + "\\BSSP.temp";
File.Copy(filename, tempname);
_ = new FileInfo(tempname);
List<byte> discoveredFootBytes = new List<byte>();
bool footerFound = false;
bool actualFooterFound = false;
int i = 0;
using (BinaryReader reader = new BinaryReader(new FileStream(tempname, FileMode.Open)))
{
byte b = 0xFF;
while (true)
{
try
{
b = reader.ReadByte();
}
catch
{
break;
}
if (actualFooterFound)
{
data.Add(b);
i++;
}
else if (footerBytes.Contains(b) && !discoveredFootBytes.Contains(b))
{
discoveredFootBytes.Add(b);
if ((discoveredFootBytes.Count == 4) && footerFound)
{
actualFooterFound = true;
}
else if ((discoveredFootBytes.Count == 4))
{
footerFound = true;
}
}
else
{
discoveredFootBytes.Clear();
}
}
}
File.Delete(tempname);
List<byte> stripped = new List<byte>();
foreach (byte b in data)
{
if (b != 0x00)
{
stripped.Add(b);
}
}
if (stripped.Count > 0)
{
return System.Text.Encoding.Default.GetString(stripped.ToArray());
} else
{
return "";
}
}
}
}