6

The following program turns off the monitor. It sometimes crashes when I run it, and it sometimes doesn't. The disassembly just points to a random location like 0x00011000, and has no real information.

If I recompile the program and run it, the recompiled version runs fine while I'm testing it. But the next time I really need to use it, it crashes again, and I need to recompile it... making me regret doing this in the first place.

I have no idea how to consistently reproduce the error. (That is, other than running it when I need it most desperately and watching it crash.)

What could be causing a random crash in this program?

#include <Windows.h>
#include <tchar.h>

int WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{
    return SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, 2);
}

I'm using Windows 7 x64, and compiling this as a 32-bit program. I believe I've tried the same thing with 64-bit and received the same result, though I'm not 100% certain.


Edit 1:

  • If anyone actually reproduces this, please post a comment and let me know, I'm curious if others can reproduce this.

  • I'm currently testing a slightly more trimmed-down version myself (which doesn't depend on the C runtime):

    #include <Windows.h>
    #pragma comment(linker, "/NoDefaultLib")
    #pragma comment(linker, "/Entry:mainCRTStartup")
    #pragma comment(linker, "/Subsystem:Windows")
    
    int mainCRTStartup()
    {
        return SendMessageW(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, 2);
    }
    
    /*
    Base64 version of this program, in case you want to use it:
    TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4gaW4gRE9TIG1vZGUuDQ0KJAAAAAAAAAABkN3fRfGzjEXxs4xF8bOMhv7ujEbxs4xF8bKMRPGzjIb+0IxE8bOMhv7pjETxs4xSaWNoRfGzjAAAAAAAAAAAUEUAAEwBAQBYIgROAAAAAAAAAADgAA8BCwEHCgACAAAAAAAAAAAAAAgQAAAAEAAAACAAAAAAQAAAEAAAAAIAAAQAAAAAAAAABAAAAAAAAAAAIAAAAAIAAAAAAAACAAAEAAAQAAAQAAAAABAAABAAAAAAAAAQAAAAAAAAAAAAAAAoEAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAudGV4dAAAAHQAAAAAEAAAAAIAAAACAAAAAAAAAAAAAAAAAAAgAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYEAAAAAAAAGoCaHDxAABoEgEAAGj//wAA/xUAEEAA99gbwPfYw8zMUBAAAAAAAAAAAAAAaBAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFgQAAAAAAAAQgJTZW5kTWVzc2FnZVcAAFVTRVIzMi5kbGwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
    */
    

    Currently, this version works... but then again, so does the previous one, when I recompile it. If it turns out that this one doesn't crash, I'll post it here.

  • If you'd like to reproduce this, here's my suggestion: Compile the program, let it marinate for a day or two. :) When you've used the computer for a while, try running the program a couple of times... when I try that, I usually get an error, until I recompile the program afresh.


Edit 2:

For some reason, whenever you want to show people a problem, it magically gets solved. Ditto the case here. I'll keep on trying to reproduce the error, but at the moment, it seems to be working fine. :\ (I have a suspicion that it might be because of installing Windows 7 SP1, but I really doubt it... if I find out I'll post here.)

Sorry about this everyone...


Edit 3:

Okay... as it happens, whenever you need to reproduce a bug, you can't. :|

However, at least I found something else: it seems that the correct window to send the message to is the window returned by GetShellWindow(). Hopefully that'll be useful for someone else.

Joshua
  • 40,822
  • 8
  • 72
  • 132
user541686
  • 205,094
  • 128
  • 528
  • 886
  • +1. That is really messed up. How on earth did you ever stumble upon this gem? – Mikola Jun 24 '11 at 04:39
  • @Mikola: Why, I used the Scientific Process, of course! Isn't that how all discoveries are made?! – user541686 Jun 24 '11 at 04:41
  • Could you try changing return SendMessage to just return 0, and the SendMessage on the line before it... – X-Istence Jun 24 '11 at 04:50
  • What else is different about the environment when you really need it to work? Other processes running, for example? – Martyn Lovell Jun 24 '11 at 04:53
  • @X-lstence: That doesn't change anything. I've tried `return 0`, I've tried calling `ExitProcess`, I've even tried calling `CoInitialize`... nothing's worked. :( – user541686 Jun 24 '11 at 04:55
  • @Martyn: The only thing that I notice being different is that I really want my monitor to be off; other than that, no idea! :\ – user541686 Jun 24 '11 at 04:56
  • @Mehrdad: Have you tried running this on a different computer? Or rather several different computers with different configurations (i.e. different graphics cards, different driver versions, different OSes, etc.)? – In silico Jun 24 '11 at 05:37
  • @In silico: Nope, I haven't... I often can't even reproduce it on my own computer, let alone others... – user541686 Jun 24 '11 at 05:39
  • @Mehrdad: To be quite honest the code works perfectly fine on my Windows 7 64-bit machines. I seriously suspect an issue with the graphics driver. I don't see any problems with the code in your question. – In silico Jun 24 '11 at 05:41
  • @In silico: But then, why would it work immediately afterwards, when I recompile it? (Yeah, I don't see any problem with the code either, that's why it's weird...) – user541686 Jun 24 '11 at 05:45
  • @Mehrdad: It might be a big coincidence. There isn't anything in your code that would make it run differently in the manner you describe. Seriously, try running the executable on a different (non-development) machine and see what happens. – In silico Jun 24 '11 at 05:49
  • @In silico: A *big* coincidence indeed, since it's consistent about that... I'll try to catch a crash dump or something next time. – user541686 Jun 24 '11 at 05:50
  • @Mehrdad: Please do. At least we'll have some idea what's going on. – In silico Jun 24 '11 at 05:54
  • 1
    Theory: Another app is doing DLL injection, window hooking, or has a creative way to get into all processes. (Just look at the number of questions on S.O. asking how to accomplish this!) Security software is notorious for doing this because they want to "help" your process. The code injected into your process perhaps has a hidden window and a buggy hook. Hookup windbg and run the lmvm command (I think that it) to see all the DLLs running at the time of crash. – selbie Jun 25 '11 at 02:16
  • Hey Mehrdad we're removing tag heisenbug; but I spent a long time looking at this and @selbie's comment is clearly the correct answer. – Joshua Aug 17 '19 at 17:15

3 Answers3

2

Perhaps you've already seen this but the gist of this article by Windows god Raymond Chen is that using HWND_BROADCAST in this way is not recommended. I found this via comments on a site that shall not be named, to the effect that the sample code you are using here, while popular, is not the right way to handle monitor powerdown.

This does not explain why you are seeing exactly what you are seeing, but it does offer some evidence that the code in question is suspect.

Steve Townsend
  • 53,498
  • 9
  • 91
  • 140
0

Configure your virus scanner to leave the app alone and not interfere with it.

Your app is too close to the evil winmain to ignore virus scanners here.

Stefan
  • 43,293
  • 10
  • 75
  • 117
0

The only thing that makes any sense re. your statement that it works if you recompile it is that something is hashing the exe and interfering with it in some way. That something would 99 times out of a 100 be a virus scanner - but you say you don't have one?

  1. You build the exe. It has a hash of 0x1234.
  2. You run it. The virus scanner hashes it, allows it to run, then decides that it is doing something it doesn't like (such as broadcasting shutdown messages to all windows).
  3. You run it again. The virus scanner says "look that 0x1234 is starting up again; I'm going to patch it to stop it broadcasting shutdown messages, or maybe I'll just stop it running at all".
  4. You rebuild the exe. It has a new hash of 0x4321 (the hash changes solely because it has a new creation/modified date).
  5. Go back to 2.
Blip
  • 46
  • 1