• The Old New Thing

    There is no /8TB flag on 64-bit Windows

    • 36 Comments

    A customer reported that their 64-bit application was crashing on Windows 8.1. They traced the problem back to the fact that the user-mode address space for 64-bit applications on Windows 8.1 is 128TB, whereas it was only 8TB on earlier versions of Windows for x64. They wanted to know whether there was a compatibility mode that they could set for their application to say "Give me only 8TB please."

    No, there is no compatibility mode to shrink the user-mode address space down to 8TB.¹ You get it all, like it or not.

    Allowing 64-bit applications to opt out of the 128TB address space has implications for the rest of the system, such as reducing the strength of ASLR.

    As for how they ended up having a dependency on the address space being at most 8TB, they didn't say, but I have a guess: They are using the unused bits for tagging.

    If you are going to use tagged pointers, you need to put your tag bits in the least significant bits, since those are bits you control. For example, if you align all your objects on 16-byte boundaries, then you have four available bits for tagging. If you're going to use upper bits for tagging, at least verify that those upper bits are available.

    ¹ If anything, the user-mode address space will only grow over time. The original 8TB limit in earlier versions of Windows was due to the lack of a CMPXCHG16B instruction, but now that the instruction is available (and support for it deemed mandatory), the full 256TB address space is available to the operating system, and right now, it decides to split the address space evenly between user mode and kernel mode.

  • The Old New Thing

    What's the point of giving my unnamed object proper security attributes since unnamed objects aren't accessible outside the process anyway (or are they?)

    • 10 Comments

    Recall that the NULL DACL grants total access to everybody. Both parts of this sentence are important to note.

    • Everybody: This means everybody. No authentication required. It includes Guest. It includes Anonymous. It includes port scanners. It includes that creepy guy who hangs around the convenience store late at night.
    • Total access: This is more than just read and write access. It includes taking ownership. It includes deleting the object. It includes changing the object's security to lock you out of your own object.

    Suppose you're a bit lazy and you decide, "Eh, I know that a NULL DACL grants total access to everybody but since I'm creating an unnamed object, nobody can access the object anyway, so it really doesn't matter what security attributes I put on it, right?"

    Um, no. Unnamed objects can be accessed. It's just that they can't be accessed by name.

    Other ways of getting a handle to an unnamed object are to duplicate the handle (and the Duplicate­Handle function will gladly duplicate handles across processes) or to inherit it.

    Therefore, if you create an object with a NULL DACL, you are exposing it to everybody who has PROCESS_DUP_HANDLE permission. Which is a lot of people. And one of them may in turn be rather sloppy with their security and let the handle escape further.

    Just do the right thing. Give the object the correct security attributes. (If you don't intend to use the object outside your process, then the default security attributes are probably just fine.)

    Besides, it's easier to create an object with default security than it is to create an object with custom security, so just do the default thing and save yourself a bunch of typing.

  • The Old New Thing

    Adding a little marker to your comments in Microsoft Word

    • 14 Comments

    This is a trick I learned while participating in a document review meeting. Before the meeting each reviewer reads the document and adds comments. All the reviewers and the document author get together, and during the meeting, we go through each comment, discuss it, and come to a conclusion. The results are recorded at the end of the comment under headings like "DISCUSSION", "RECOMMEND", or "CONSIDER".

    Bob Smith 2 hours ago
    When should a developer use a Widget to solve a problem, and when should they use a Doodad? The choice is not clear.
    → DISCUSSION: Widgets are when there is a choice between two options. Doodads are when there is a decision that can have multiple answers.
    → RECOMMEND: Add guidance.

    The meeting leader deftly entered the → character into the document without needing to pull down any menus. And this wasn't the big, bulky arrow you get when you do the -> autocorrect.

    The meeting leader explained, "I just hit the TAB key. In a comment, it enters an arrow. I discovered this by accident many years ago. I have no idea if this is a bug or a feature, but it still works!"

  • The Old New Thing

    Why do events logged by the ReportEvent function show up in the wrong order in the Event Viewer?

    • 18 Comments

    A customer observed that when their service logs multiple events in rapid succession, they sometimes show up out of order in Event Viewer. Specifically, the order of events that all occur within the same second are sometimes mis-ordered relative to each other. Is this expected?

    Events in the event viewer are timestamped only to one-second resolution. The EVENT­LOG­RECORD structure reports time in UNIX format, namely, seconds since January 1, 1970.

    Experimentation suggested that the Event Viewer sorts events by timestamp, but it does not use a stable sort, so multiple events that occur within the same second end up in an unpredictable order.

    Not much you can do about it, but at least now you know that you're not hallucinating.

  • The Old New Thing

    How can I make the touch keyboard appear automatically when focus enters an edit control in my program?

    • 13 Comments

    By default, the Windows 8 touch keyboard does not appear automatically when focus is placed on an edit control in a desktop program. To change the behavior for your program, just use this one weird trick:

    HRESULT EnableTouchKeyboardFocusTracking()
    {
      ComPtr<IInputPanelConfiguration> configuration;
      HRESULT hr =
        CoCreateInstance(__uuidof(InputPanelConfiguration), nullptr,
          CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&configuration));
      if (SUCCEEDED(hr)) {
        hr = configuration->EnableFocusTracking();
      }
      return hr;
    }
    

    You create an instance of the Input­Panel­Configuration object and ask it to enable focus tracking. This is a per-process setting, and once set, it cannot be unset.

    Let's use this function in a Little Program so you can play with it. Most of the work in setting up the program is creating two controls: an edit control and a button. If I had just one control, then you wouldn't be able to see how the keyboard automatically appears and disappears when focus moves between an edit control and some other type of control.

    Remember that Little Programs do little to no error checking. Start with the scratch program and make these changes:

    #define STRICT
    #include ...
    #include <shobjidl.h>
    #include <inputpanelconfiguration.h>
    #include <wrl\client.h>
    #include <wrl\event.h>
    
    using namespace Microsoft::WRL;
    
    HINSTANCE g_hinst;                          /* This application's HINSTANCE */
    HWND g_hwndChild;                           /* Optional child window */
    HWND g_hwndButton;
    HWND g_hwndLastFocus;
    
    void
    DoLayout(HWND hwnd, int cx, int cy)
    {
      if (g_hwndChild) {
        MoveWindow(g_hwndChild, 0, 0, cx - 100, cy, TRUE);
      }
      if (g_hwndButton) {
        MoveWindow(g_hwndButton, cx - 100, 0, 100, 50, TRUE);
      }
    }
    
    void
    OnSize(HWND hwnd, UINT state, int cx, int cy)
    {
      DoLayout(hwnd, cx, cy);
    }
    
    BOOL
    OnCreate(HWND hwnd, LPCREATESTRUCT lpcs)
    {
      g_hwndChild = CreateWindow(TEXT("edit"), nullptr,
        WS_CHILD | WS_VISIBLE | WS_BORDER | ES_MULTILINE,
        0, 0, 100, 100, hwnd, nullptr, g_hinst, 0);
      g_hwndButton = CreateWindow(TEXT("button"), TEXT("Send"),
        WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
        0, 0, 100, 100, hwnd, nullptr, g_hinst, 0);
    
      EnableTouchKeyboardFocusTracking();
      return TRUE;
    }
    
    // OnActivate incorporated by reference.
    
     HANDLE_MSG(hwnd, WM_ACTIVATE, OnActivate);
    
    BOOL
    InitApp(void)
    {
      ...
      wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1);
      ...
    }
    

    We position the edit control on the left hand side of the window and put the button in the upper right corner. We enable focus tracking on the touch keyboard, and just to make it easier to see where the edit control is, we give the frame with the app-workspace color.

    Although we summon the touch keyboard when focus enters the edit control, we do nothing to prevent the keyboard from covering what the user is typing. This is one of the reasons that the touch keyboard does not appear automatically when focus is placed in an edit control of a desktop program. It would end up covering the edit control the user is trying to type into!

    We'll work on fixing this problem next week.

  • The Old New Thing

    Under what conditions can SetFocus crash? Another debugging investigation

    • 10 Comments

    A customer asked, "Under what conditions can Set­Focus crash?"

    We have been going through our error reports and are puzzled by this one. The call stack is as follows:

    user32!_except_handler4
    ntdll!ExecuteHandler2@20
    ntdll!ExecuteHandler@20
    ntdll!RtlDispatchException
    ntdll!_KiUserExceptionDispatcher@8
    0x130862
    user32!UserCallWinProcCheckWow
    user32!__fnDWORD
    ntdll!_KiUserCallbackDispatcher@12
    user32!NtUserSetFocus
    contoso!DismissPopup
    

    At the point of the crash, the Dismiss­Popup function is calling Set­Focus to restore focus to a window handle that we got from an earlier call to Get­Active­Window. Is this safe? We imagine it might crash if the message handler for the window was unloaded from memory without being properly unregistered; are there any other reasons? More to the point, is there any way to avoid the problem (without fixing the root cause of the crash, which we may not be able to do, e.g. if that window was created by third-party code)?

    The full dump file can be found on <location>. The password is <xyzzy>.

    Indeed, what the customer suspected is what happened, confirmed by the dump file provided.

    The code behind the window procedure got unloaded. User­Call­Win­Proc­Check­Wow is trying to call the window procedure, but instead it took an exception. The address doesn't match any loaded or recently-unloaded module probably because it was a dynamically generated thunk, like the ones ATL generates.

    There isn't much you can do to defend against this. Even if you manage to detect the problem and avoid calling Set­Focus in this problematic case, all you're doing is kicking the can further down the road. Your program will crash the next time the window receives a message, which it eventually will. (For example, the next time the user changes a system setting and the WM_SETTING­CHANGE message is broadcast to all top-level windows, or the user plugs in an external monitor and the WM_DISPLAY­CHANGE message is broadcast to all top-level windows.)

    Basically, that other component pulled the pin on a grenade and handed it to your thread. That grenade is going to explode sooner or later. The only question is when.

    Such is the danger of giving your application an extension model that allows arbitrary third party code to run. The third party code can do good things to make your program more useful, but it can also do bad things to make your program crash.

  • The Old New Thing

    When designing your user interface, be mindful of the selection-readers

    • 47 Comments

    Occasionally, there will be a feature along the lines of "Whenever the user selects some text, we will pop up an X." And then I have to remind them about so-called selection readers.

    Selection readers are people who habitually select text in a document as they read it. It can be quite maddening looking over the shoulder of a selection reader, because you will see seemingly-random fragments of text get selected, and for those who are selection-deselection readers, the text will almost immediately get cleared. It's like the entire document is blinking with selections. (Other variations of the selection reader are the double-click reader who double-clicks words on the page, the margin-click reader who clicks in the margin, and the hover reader who merely hovers the mouse without clicking.)

    There are a number of theories behind why some people are selection readers.

    • It's a nervous habit to keep one's fingers occupied, similar to spinning a pen.
    • It marks one's place in the document.
    • It gives a sense of accomplishment as one progresses through the document.
    • It helps the eye follow the reading location in the document during a scroll operation.

    I am not a selection reader, but I do click in the document with some regularity. I do this for two reasons.

    1. To give focus to the document area, so that scrolling the mouse wheel or hitting PgDn will scroll the document text.
    2. To place the caret inside the viewport.

    The second reason needs some explanation.

    The caret is the blinking line that shows where your next typed character will be inserted. You can scroll the document so much that the caret goes out of the viewport. For example, if you never click in the document but merely scroll through it, the caret will be at the top of the document, even though you are reading page 25 of 50.

    And then you hit PgDn thinking that you're scrolling down one screen, but instead you're going to the middle of page one. Congratulations, you just lost your place and jumped backward 24 pages.

    Furthermore, there are some programs which are really twitchy about the caret. If you manage to scroll the caret off screen, they will say, "Sure, go ahead and scroll the caret off screen," but then you breathe on the program funny (say, by switching to another program, then switch back with Alt+Tab), and it says, "Whoa, your caret is waaaaay off screen! Let me help you by scrolling the caret back on screen. No need to thank me. Just helping out."

    Of course, what those programs ended up doing is ripping me from page 25 back to page one.

    That's why I consciously click in the document a few times after every scroll operation. It's not yet a habitual operation, so I will sometimes forget, and then just my luck, that's the time I accidentally hit PgDn or or Alt+Tab and get teleported backward in the document.

  • The Old New Thing

    Dubious security vulnerability: Luring somebody into your lair

    • 31 Comments

    A security report was received that went something like this:

    The XYZ application does not load its DLLs securely. Create a directory, say, C:\Vulnerable, and copy XYZ.EXE and a rogue copy of ABC.DLL in that directory. When C:\Vulnerable\XYZ.EXE is run, the XYZ program will load the rogue DLL instead of the official copy in the System32 directory. This is a security flaw in the XYZ program.

    Recall that the directory is the application bundle, The fact that the XYZ.EXE program loads ABC.DLL from the application directory rather than the System32 directory is not surprising because the ABC.DLL has been placed inside the XYZ.EXE program's trusted circle.

    But what is the security flaw, exactly?

    Let's identify the attacker, the victim, and the attack scenario.

    The attacker is the person who created the directory with the copy of XYZ.EXE and the rogue ABC.DLL.

    The victim is whatever poor sap runs the XYZ.EXE program from the custom directory instead of from its normal location.

    The attack scenario is

    • Attacker creates a directory, say, C:\Vulnerable.
    • copy C:\Windows\System32\XYZ.EXE C:\Vulnerable\XYZ.EXE
    • copy rogue.dll C:\Vulnerable\ABC.DLL
    • Convince a victim to run C:\Vulnerable\XYZ.EXE.

    When the victim runs C:\Vulnerable\XYZ.EXE, the rogue DLL gets loaded, and the victim is pwned.

    But the victim was already pwned even before getting to that point! Because the victim ran C:\Vulnerable\XYZ.EXE.

    A much simpler attack is to do this:

    • Attacker creates a directory, say, C:\Vulnerable.
    • copy pwned.exe C:\Vulnerable\XYZ.EXE
    • Convince a victim to run C:\Vulnerable\XYZ.EXE.

    The rogue ABC.DLL is immaterial. All it does is crank up the degree of difficulty without changing the fundamental issue: If you can trick a user into running a program you control, then the user is pwned.

    This is another case of if I can run an arbitrary program, then I can do arbitrary things, also known as MS07-052: Code execution results in code execution.

    Note that the real copy of XYZ.EXE in the System32 directory is unaffected. The attack doesn't affect users which run the real copy. And since C:\Vulnerable isn't on the default PATH, the only way to get somebody to run the rogue copy is to trick them into running the wrong copy.

    It's like saying that there's a security flaw in Anna Kournikova because people can create things that look like Anna Kournikova and trick victims into running it.

  • The Old New Thing

    The tadpole operators explained

    • 25 Comments

    Last time,¹ I introduced the tadpole operators. As you have probably figured out by now, it was a joke. There are no new tadpole operators.

    But the sample code works. What's going on?

    The tadpole operators are pseudo-operators, like the goes to operator or the sproing operator: They take advantage of existing language features, and come with a creative story.

    The tadpole operators exploit two's complement arithmetic and overflow.² The __ENABLE_EXPERIMENTAL_TADPOLE_OPERATORS is just a red herring.

    Start with the identity for two's complement negation

    -x = ~x + 1
    

    then move the -x to the right hand side and the ~x to the left hand side:

    -~x = x + 1
    

    If that was too fast for you, we can do it a different way: start with the identity for two's complement negation

    -x = ~x + 1
    

    subtract 1 from both sides

    -x - 1 = ~x
    

    and finally, negate both sides

    x + 1 = -~x
    

    To get the decrement tadpole operator, start with

    -x = ~x + 1
    

    and substitute x = -y:

    -(-y) = ~-y + 1
    

    subtract 1 from both sides and simplify -(-y) to y.

    y - 1 = ~-y
    

    Update: Justin Olbrantz (Quantam) and Ben Voigt provide a simpler derivation, starting with the identity for two's complement negation.

    -x = ~x + 1
    Rearrange terms ~x = -x - 1
    Let x = ~y Let x = -y
    -~y = ~(~y) + 1 ~-y = -(-y) - 1
    -~y = y + 1 ~-y = y - 1

    ¹Why didn't I post it on April 1st? Well, for one thing, April 1st is overcrowded. Second, it would have interfered with the run-up to the //build conference. And third, yesterday was a holiday in the United States, and I tend to schedule lighter fare on holidays.

    ²This means that they don't work on a machine that does not use two's complement, or one which checks overflow. Still, maybe they'll be useful if you're entering the IOCCC or some other contest which values minimal code size or obfuscation (or both).

  • The Old New Thing

    New C++ experimental feature: The tadpole operators

    • 116 Comments

    How often have you had to write code like this:

    x = (y + 1) % 10;
    x = (y + 1) * (z - 1);
    x = (wcslen(s) + 1) * sizeof(wchar_t);
    

    Since the + and - operators have such low precedence, you end up having to parenthesize them a lot, which can lead to heavily nested code that is hard to read.

    Visual Studio 2015 RC contains a pair of experimental operators, nicknamed tadpole operators. They let you add and subtract one from an integer value without needing parentheses.

    x = -~y % 10;
    x = -~y * ~-z;
    x = -~wcslen(s) * sizeof(wchar_t);
    

    They're called tadpole operators because they look like a tadpole swimming toward or away from the value. The tilde is the tadpole's head and the hyphen is the tail.

    Syntax Meaning Mnemonic
    -~y y + 1 Tadpole swimming toward a value makes it bigger
    ~-y y - 1 Tadpole swimming away from a value makes it smaller

    To enable the experimental tadpole operators, add this line to the top of your C++ file

    #define __ENABLE_EXPERIMENTAL_TADPOLE_OPERATORS
    

    For example, here's a simple program that illustrates the tadpole operators.

    #define __ENABLE_EXPERIMENTAL_TADPOLE_OPERATORS 
    #include <ios>
    #include <iostream>
    #include <istream>
     
    int __cdecl main(int, char**)
    {
       int n = 3;
       std::cout << "3 + 1 = " << -~n << std::endl;
       std::cout << "(3 - 1) * (3 + 1) " << ~-n * -~n << std::endl;
       return 0;
    }
    

    Remember that these operators are still experimental. They are not officially part of C++, but you can play with them and give your feedback here learn more about them here.

Page 5 of 455 (4,544 items) «34567»