• The Old New Thing

    Windows 7 no longer tries to guess application size and other information


    Back in the old days, if an application did not provide information like its Estimated Size or Install Date, then the Add/Remove Programs control panel tried to guess the values by searching your hard drives for files and directories that bore a superficial resemblance to the application. (Note that I use the word drives in the plural. It actually searched all of your drives, because some applications may have been installed to secondary drives. I can imagine the bug report that led to this extended search. "I installed LitWare 2000 to my D: drive, and the Add/Remove Programs control panel shows no information for it. You should have found it on my D: drive, because (like many power users) I install all my applications to my D drive to maintain free space on my C drive.")

    Time passed, and the name of the Add/Remove Programs control panel changed several times. It became Add or Remove Programs in Windows XP, changing the slash to the word or. In Windows Vista, its name changed to Programs and Features, but at least the name has been stable since then.

    In Windows 7, the "search your hard drive looking for the application" fallback algorithm was removed. If an application did not provide information such as its estimated size or install location, then Windows now just says, "Well, tough on you." My guess is that the search was removed because the vast majority of applications now provide the information directly, so the extra cost of trying to hunt it down for the last few application was not worth the benefit.

    There is still one tiny thing that Windows will guess: The installation date. But it doesn't have go hunting through your hard drive to guess that. It merely infers it from the last-modified date on the uninstall metadata itself!

  • The Old New Thing

    Answer to previous exercise


    If the program starts with the mouse already in the client area without moving, why do you get a beep?

    Because of the spurious WM_MOUSEMOVE message that is generated when a window is created. In this case, the spurious message is a good thing, since it lets us do our mouse work at window creation.
  • The Old New Thing

    How do I get the color depth of the screen?


    How do I get the color depth of the screen? This question already makes an assumption that isn't always true, but we'll answer the question first, then discuss why the answer is wrong.

    If you have a device context for the screen, you can query the color depth with a simple arithmetic calculation:

    colorDepth = GetDeviceCaps(hdc, BITSPIXEL) *
                 GetDeviceCaps(hdc, PLANES);

    Now that you have the answer, I'll explain why it's wrong, but you can probably guess the reason already.

    Two words: Multiple monitors.

    If you have multiple monitors connected to your system, each one can be running at a different color depth. For example, your primary monitor might be running at 32 bits per pixel, while the secondary is stuck at 16 bits per pixel. When there was only one monitor, there was such a thing as the color depth of the screen, but when there's more than one, you first have to answer the question, "Which screen?"

    To get the color depth of each monitor, you can take your device context and ask the window manager to chop the device context into pieces, each corresponding to a different monitor.

    EnumDisplayMonitors(hdc, NULL, MonitorEnumProc, 0);
    // this function is called once for each "piece"
    BOOL CALLBACK MonitorEnumProc(HMONITOR hmon, HDC hdc,
                                  LPRECT prc, LPARAM lParam)
       // compute the color depth of monitor "hmon"
       int colorDepth = GetDeviceCaps(hdc, BITSPIXEL) *
                        GetDeviceCaps(hdc, PLANES);
       return TRUE;

    If you decide to forego splitting the DC into pieces and just ask for "the" color depth, you'll get the color depth information for the primary monitor.

    As a bonus (and possible optimization), there is a system metric GetSystemMetrics(SM_SAMEDISPLAYFORMAT) which has a nonzero value if all the monitors in the system have the same color format.

  • The Old New Thing

    It rather involved being on the other side of this airtight hatchway: Invalid parameters from one security level crashing code at the same security level (yet again)


    It's the bogus vulnerability that keeps on giving. This time a security researcher found a horrible security flaw in Sys­Alloc­String­Len:

    The Sys­Alloc­String­Len function is vulnerable to a denial-of-service attack. [Long description of reverse-engineering deleted.]

    The Sys­Alloc­String­Len does not check the length parameter properly. If the provided length is larger than the actual length of the buffer, it may encounter an access violation when reading beyond the end of the buffer. Proof of concept:

    SysAllocStringLen(L"Example", 0xFFFFFF);

    Credit for this vulnerability should be given to XYZ Security Labs. Copyright © XYZ Security Labs. All rights reserved.

    As with other issues of this type, there is no elevation. The attack code and the code that crashes are on the same side of the airtight hatchway. If your goal was to make the process crash, then instead of passing invalid parameters to the Sys­Alloc­String­Len function, you can launch the denial of service attack much more easily:

    int __cdecl main(int, char**)

    Congratulations, you just launched a denial-of-service attack against yourself.

    In order to trigger an access violation in the Sys­Alloc­String­Len function, you must already have had enough privilege to run code, which means that you already have enough privilege to terminate the application without needing the Sys­Alloc­String­Len function.

    Once again, we have a case of MS07-052: Code execution results in code execution

    Earlier in the series:

    Bonus bogus vulnerability report:

    The Draw­Text function is vulnerability to a denial-of-service attack because it does not validate that the lpchText parameter is a valid pointer. If you pass NULL as the second parameter, the function crashes. We have found many functions in the system which are vulnerable to the same issue.

    ¹ Now, of course, if there were some way you could externally induce a program into passing invalid parameters to the Sys­Alloc­String­Length function, then you'd be onto something. But even then, the vulnerability would be in the program that is passing the invalid parameters, not in the Sys­Alloc­String­Length function itself.

  • The Old New Thing

    The publicity machine doesn't stop: TechNet podcast interview


    The TechNet Magazine Podcast page has just posted their February 2007 entry, which includes an interview with little old me in the second half. I haven't listened to the whole interview yet, but what struck me immediately is that I was pretty darned punchy and goofy, whereas I think the host was trying to take a more serious tone. Oops.

  • The Old New Thing

    Email tips from Adam Phillabaum


    Adam Phillabaum of Doing Boeing (who kept the name even though he left Boeing and now works for PayScale) has his own tips for writing email. Recommended reading.

  • The Old New Thing

    How to pretend that you attended my talk at UIUC Reflections|Projections 2009


    Step 1: Buy a 1.55-ounce Hershey's Milk Chocolate Bar from a convenience store, supermarket, or (if truly desperate) online.

    Step 2: Print out this candy bar wrapper.

    Step 3: Trim wrapper on registration marks and wrap around candy bar.

    Step 4: Stay up late the night before you plan on watching the video by partying with Ryan North and teaching him how to play beer pong.

    Step 5: Force yourself to wake up the next morning and watch the recorded video of my talk while trying desperately to stay awake. The candy bar might help.

    Note: Although most steps are optional, they are essential if you want an accurate simulation.

  • The Old New Thing

    News flash: Companies change their product to appeal to their customers


    There was some apparent uproar because there was an industry which "changed the flavoring of their product depending on which market segment they were trying to appeal to."

    Well duh, don't all industries do this?

    The reason why this even remotely qualified as news didn't appear until the last five words of the article!

  • The Old New Thing

    How organizations inadvertently confirm facts when they try not to


    On the Media in its story "Fact? Check!" forwarded the revelation (uncovered by the PBS program Frontline in the first part of their "News War" series) that the fact that the United States Justice Department launches a leak investigation implicitly confirms the leak! That's because one of the prerequisites for a leak investigation is that the leaked information actually be true.

    Lowell Bergman: The information has to be accurate?

    Dave Szady: Yes.

    Lowell Bergman: So when the government announces a leak investigation and it comes to your office, it's confirming that the report in the newspaper, for example, or on television, was true.

    Dave Szady: Yes. Indirectly, yes.

    That reminded me of a similar "inadvertent confirmation" from a local news story many years ago. Someone was admitted to the hospital with acute poisoning, and the local newspaper called to determine whether it was an attempted suicide. The hospital confirmed that the person had been admitted, but declined to discuss whether it was due to a suicide attempt. "Our privacy policy forbids us from revealing any further information about patients who are admitted after an attempted suicide."

  • The Old New Thing

    If only DLLs can get DllMain notifications, how can an EXE receive a notification when a thread is created (for example)?


    When a DLL is loaded, it receives a DLL_PROCESS_ATTACH notification, and when it is unloaded (or when the process terminates), it gets a DLL_PROCESS_DETACH notification. DLLs also receive DLL_THREAD_ATTACH notifications when a thread is created and DLL_THREAD_DETACH notifications when a thread exits. But what if you are an EXE? EXEs don't have a Dll­Main, so there is no way to receive these notifications.

    The trick here is to hire a lackey.

    Create a helper DLL, called, say, LACKEY.DLL. Your EXE links to the lackey, and the lackey's job is to forward all Dll­Main notifications back to your EXE. The DLL would naturally have to have a way for your EXE to provide the callback address, so you might have a function Register­Lackey­Callback.

    LACKEYNOTIFICATION g_lackeyNotification;
    void RegisterLackeyCallback(LACKEYNOTIFICATION lackeyNotification)
     g_lackeyNotification = lackeyNotification;
    BOOL WINAPI DllMain(
        HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved)
     if (g_lackeyNotification) g_lackeyNotification(dwReason);
     return TRUE;

    Of course, it is rather extravagant to hire a lackey just for this one task, so you will probably just add lackey responsibilities to some other DLL you've written.

    I don't know if there's a name for this design pattern, so I'm just going to call it the hired lackey pattern.

Page 388 of 455 (4,549 items) «386387388389390»