• The Old New Thing

    Why are the keyboard scan codes for digits off by one?

    • 17 Comments

    In Off by one what, exactly?, my colleague Michael Kaplan wrote

    And this decision long ago that caused the scan codes to not line up for these digits when they could have...

    The word that struck me there was "decision".

    Because it wasn't a "decision" to make the scan codes almost-but-not-quite line up with digits. It was just a coincidence.

    If you look at the scan code table from Michael's article

    you can see stretches of consecutive scan codes, broken up by weird places where the consecutive pattern is violated. The weirdness makes more sense when you look at the original IBM PC XT keyboard:

    01
    Esc
    02
    1
    03
    2
    04
    3
    05
    4
    06
    5
    07
    6
    08
    7
    09
    8
    0A
    9
    0B
    0
    0C
    0D
    =
    0E
    0F
    10
    Q
    11
    W
    12
    E
    13
    R
    14
    T
    15
    Y
    16
    U
    17
    I
    18
    O
    19
    P
    1A
    [
    1B
    ]
    1C
    1D
    Ctrl
    1E
    A
    1F
    S
    20
    D
    21
    F
    22
    G
    23
    H
    24
    J
    25
    K
    26
    L
    27
    ;
    28
    '
    29
    `
    2A
    2B
    \
    2C
    Z
    2D
    X
    2E
    C
    2F
    V
    30
    B
    31
    N
    32
    M
    33
    ,
    34
    .
    35
    /
    36
    37
    *
    38
    Alt
    39
    Space
    3A
    Caps

    With this presentation, it becomes clearer how scan codes were assigned: They simply started at 01 and continued through the keyboard in English reading order. (Scan code 00 is an error code indicating keyboard buffer overflow.) The reason for the keyboard scan code being off-by-one from the digits is merely due to the fact that there was one key to the left of the digits. If there were two keys to the left of the digits, they would have been off by two.

    Of course, if the original keyboard designers had started counting from the lower left corner, like all right-thinking mathematically-inclined people, then this sort-of-coincidence would never have happened. The scan codes for the digits would have been 2E through 37, and nobody would have thought anything of it.

    It's a testament to the human brain's desire to find patterns and determine a reason for them that what is really just a coincidence gets interpreted as some sort of conspiracy.

  • The Old New Thing

    Why does each drive have its own current directory?

    • 39 Comments

    Commenter Dean Earley asks, "Why is there a 'current directory' AND an current drive? Why not merge them?"

    Pithy answer: Originally, each drive had its own current directory, but now they don't, but it looks like they do.

    Okay, let's unwrap that sentence. You actually know enough to answer the question yourself; you just have to put the pieces together.

    Set the wayback machine to DOS 1.0. Each volume was represented by a drive letter. There were no subdirectories. This behavior was carried forward from CP/M.

    Programs from the DOS 1.0 era didn't understand subdirectories; they referred to files by just drive letter and file name, for example, B:PROGRAM.LST. Let's fire up the assembler (compilers were for rich people) and assemble a program whose source code is on the A drive, but sending the output to the B drive.

    A>asm foo       the ".asm" extension on "foo" is implied
    Assembler version blah blah blah
    Source File: FOO.ASM
    Listing file [FOO.LST]: NUL throw away the listing file
    Object file [FOO.OBJ]: B: send the object file to drive B

    Since we gave only a drive letter in response to the Object file prompt, the assembler defaults to a file name of FOO.OBJ, resulting in the object file being generated as B:FOO.OBJ.

    Okay, now let's introduce subdirectories into DOS 2.0. Suppose you have want to assemble A:\SRC\FOO.ASM and put the result into B:\OBJ\FOO.OBJ. Here's how you do it:

    A> B:
    B> CD \OBJ
    B> A:
    A> CD \SRC
    A> asm foo
    Assembler version blah blah blah
    Source File: FOO.ASM
    Listing file [FOO.LST]: NUL
    Object file [FOO.OBJ]: B:
    

    The assembler reads from A:FOO.ASM and writes to B:FOO.OBJ, but since the current directory is tracked on a per-drive basis, the results are A:\SRC\FOO.ASM and B:\OBJ\FOO.OBJ as desired. If the current directory were not tracked on a per-drive basis, then there would be no way to tell the assembler to put its output into a subdirectory. As a result, DOS 1.0 programs were effectively limited to operating on files in the root directory, which means that nobody would put files in subdirectories (because their programs couldn't access them).

    From a DOS 1.0 standpoint, changing the current directory on a drive performs the logical equivalent of changing media. "Oh look, a completely different set of files!"

    Short attention span.

    Remembering the current directory for each drive has been preserved ever since, at least for batch files, although there isn't actually such a concept as a per-drive current directory in Win32. In Win32, all you have is a current directory. The appearance that each drive has its own current directory is a fake-out by cmd.exe, which uses strange environment variables to create the illusion to batch files that each drive has its own current directory.

    Dean continues, "Why not merge them? I have to set both the dir and drive if i want a specific working dir."

    The answer to the second question is, "They already are merged. It's cmd.exe that tries to pretend that they aren't." And if you want to set the directory and the drive from the command prompt or a batch file, just use the /D option to the CHDIR command:

    D:\> CD /D C:\Program Files\Windows NT
    C:\Program Files\Windows NT> _
    

    (Notice that the CHDIR command lets you omit quotation marks around paths which contain spaces: Since the command takes only one path argument, the lack of quotation marks does not introduce ambiguity.

  • The Old New Thing

    Why does TaskDialog return immediately without showing a dialog? - Answer

    • 0 Comments

    Last time, I left an exercise to determine why the Task­Dialog function was not actually displaying anything. The problem had nothing to do with an invalid window handle parameter and had all to do with original window being destroyed.

    My psychic powers told me that the window's WM_DESTROY handler called Post­Quit­Message. As we learned some time ago, quit messages cause modal loops to exit. Since the code was calling Task­Dialog after the window was destroyed, there was a WM_QUIT message still sitting in the queue, and that quit message caused the modal loop in Task­Dialog to exit before it got a chance to display anything.

    Switching to Message­Box wouldn't have changed anything, since Message­Box responds to quit messages the same way as Task­Dialog.

    (Worf was the first person to post the correct answer.)

  • The Old New Thing

    Why does my asynchronous I/O request return TRUE instead of failing with ERROR_IO_PENDING?

    • 12 Comments

    A customer reported that their program was not respecting the FILE_FLAG_OVERLAPPED flag consistently:

    My program opens a file handle in FILE_FLAG_OVERLAPPED mode, binds it to an I/O completion callback function with Bind­Io­Completion­Callback, and then issues a Write­File against it. I would expect that the Write­File returns FALSE and Get­Last­Error() returns ERROR_IO_PENDING, indicating that the I/O operation is being performed asynchronously, and that the completion function will be called when the operation completes. However, I find that some percentage of the time, the call to Write­File returns TRUE, indicating that the operation was performed synchronously. What am I doing wrong? I don't want my thread to block on I/O; that's why I'm issuing asynchronous I/O.

    When you specify FILE_FLAG_OVERLAPPED, you're promising that your program knows how to handle I/O which completes asynchronously, but it does not require the I/O stack to behave asynchronously. A driver can choose to perform your I/O synchronously anyway. For example, if the write operation can be performed by writing to cache without blocking, the driver will just copy the data to the cache and indicate synchronous completion. Don't worry, be happy: Your I/O completed even faster than you expected!

    Even though the I/O completed synchronously, all the asynchronous completion notification machinery is still active. It's just that they all accomplished their job before the Write­File call returned. This means that the event handle will still be signaled, the completion routine will still run (once you wait alertably), and if the handle is bound to an I/O completion port, the I/O completion port will receive a completion notification.

    You can use the Set­File­Completion­Notification­Modes function to change some aspects of this behavior, giving some control of the behavior of the I/O subsystem when a potentially-asynchronous I/O request completes synchronously.

  • The Old New Thing

    The overlooked computer room at school that became my "office" for a while

    • 9 Comments

    VIMH's comment on an unmarked restroom that is largely unknown reminds me of a story from my college days.

    Since my final project involved computational geometry, I was granted a key to the rooms in our department which had the computers with fancy graphical displays. (The term "fancy graphical display" is a relative one, mind you. By today's standards they would be pretty lame.) Use of the computers in these rooms was normally reserved for faculty and graduate students. During my wanderings through the department building, I discovered that there was a small storage room in an unused corner of the basement that contained not only the boxes piled high, like you might expect, but also one graphics display terminal.

    I was pleased at my discovery and even more pleased to discover over time that nobody ever came to visit. I had stumbled across the forgotten computer room.

    After a few weeks, I moved in a small tape cassette recorder (that being the fanciest audio technology I could afford at the time) so I could listen to music while I worked. Rachmaninoff's Third Piano Concerto became the mental soundtrack to my final project. Initially, I stowed the tape recorder in the corner when I left the room, but I gradually became lazy and just left it on the table next to the computer.

    This is normally the part of the story where our hero's casual mistake leads to his downfall: A custodian discovers the tape recorder, reports it to the administrator, and our hero is kicked out of the department for misuse of school facilities.

    But that's not what happened. As far as I remember, there was only one time another person paid a visit to the overlooked computer room while I was working in there. He jiggled the door handle, found it locked, and waved apologetically. (He was probably not even somebody authorized to be in the room, because if he were, he would have had a key.)

  • The Old New Thing

    Why does TaskDialog return immediately without showing a dialog?

    • 9 Comments

    A customer reported a problem with the Task­Dialog function.

    We've encountered a strange behavior in the Task­Dialog function. A user reported that when exiting our application, our program played an error beep that didn't appear to be associated with an error. After investigating, we found that the sound is coming from our application trying to display an error dialog before closing by calling Task­Dialog. The error beep is played but no dialog appears.

    Some background on the error condition that we're trying to report: We're calling Create­Window­Ex, and the window procedure creates another window in its WM_CREATE handler. It looks like the original window is destroyed before WM_CREATE is finished, so Create­Window­Ex returns ERROR_INVALID_WINDOW_HANDLE. It's not clear why this is causing Task­Dialog to fail, but this is the only scenario where we see this behavior. All other calls to Task­Dialog work as expected. We know how to fix the original problem with Create­Window­Ex, but we would like to understand what's going on with Task­Dialog in case there's another bug here.

    With a little bit of psychic powers, you can solve this customer's problem too.

    (If you have a good memory, you may have noticed that it's a variation on a previous puzzle. But I get to keep recycling it because every year, a new batch of developers stumbles across the problem.)

  • The Old New Thing

    Wildly popular computer game? The Windows product team has you covered

    • 30 Comments

    In Windows 95, the most heavily-tested computer game was DOOM. Not because the testers spent a lot of time developing test plans and test harnesses and automated run-throughs. Nope, it was because it was by far the most popular game the Windows 95 team members played to unwind.

    It was a huge breakthrough when DOOM finally ran inside a MS-DOS box and didn't require booting into MS-DOS mode any more. Now you could fire up DOOM without having to exit all your other programs first.

    I've learned that in Windows Vista, the most heavily tested game was World of Warcraft. Most members of the DirectX application compatibility team are WoW players, in addition to a large number in the Windows division overall.

    So if you have a wildly popular computer game for the PC, you can be pretty sure that the Windows team will be all over it. "For quality control purposes, I assure you."

    Related story: How to make sure your network card works with Windows.

  • The Old New Thing

    Secret passages on Microsoft main campus

    • 33 Comments

    They aren't really "secret passages" but they are definitely underutilized, and sometimes they provide a useful shortcut.

    At the northwest corner of Building 50, there are two doors. One leads to a stairwell that takes you to the second floor. That's the one everybody uses. The other door is a service entrance that takes you to the cafeteria. If your office is on the second or third floor in the northwest corner, it's faster to use the service hallway to get to the cafeteria than it is to walk to the core of the building and take the main stairs.

    There is a service tunnel that runs from the first floor of Building 86 (entrance next to the first floor cafeteria elevator) through the loading dock to the Central Garage, where you can continue to Building 85 or 84. This is not really any faster than the regular route, but it does have the advantage of being underground and mostly indoors, which is a major benefit when it is cold or raining.

    What is your favorite secret passage at your workplace?

  • The Old New Thing

    On understanding that getting married comes with changes in lifestyle

    • 13 Comments

    A friend of mine who had been married less than a year received a phone call from Adam, one of his still-single friends:

    "Hey, Joe! Irving and I are going into town, hit some bars, hang out at some clubs, wanna come along?"

    My friend replied, "Hang on a second."

    A beat.

    "Nope. Still married!"

    As far as I know, Adam and Irving are still single.

  • The Old New Thing

    Why is the origin at the upper left corner?

    • 32 Comments

    Via the Suggestion Box, Dirk Declercq asks why the default client-area coordinate origin is at the upper left corner instead of the lower left corner. (I assume he also intends for the proposed client-area coordinate system to have the y-coordinate increasing as you move towards the top of the screen.)

    Well, putting the client area origin at the lower left would have resulted in the client coordinate space not being a simple translation of the screen coordinate space. After all, the screen origin is at the upper left, too. Windows was originally developed on left-to-right systems, where the relationship between client coordinates and screen coordinates was a simple translation. Having the y-coordinate increase as you move down the screen but move up the client would have just been one of those things you did to be annoying.

    Okay, so why not place the screen origin at the lower left, too?

    Actually, OS/2 does this, and DIBs do it as well. And then everybody wonders why their images are upside-down.

    Turns out that the people who designed early personal computers didn't care much for mathematical theory. The raster gun of a television set starts at the upper left corner, continues to the right, and when it reaches the right-hand edge of the screen, it jumps back to the left edge of the screen to render the second scan line. Why did television sets scan from the top down instead of from the bottom up? Beats me. You'll have to ask the person who invented the television (who, depending on whom you ask, is Russian or American or German or Scottish or some other nationality entirely), or more specifically, whoever invented the scanning model of image rendering, why they started from the top rather than from the bottom.

    Anyway, given that the video hardware worked from top to bottom, it was only natural that the memory for the video hardware work the same way. (The Apple II famously uses a peculiar memory layout in order to save a chip.)

    Who knows, maybe if the design of early computers had been Chinese, we would be wondering why the origin was in the upper right corner with the pixels in column-major order.

    Bonus chatter: Even mathematicians can't get their story straight. Matrices are typically written with the origin element at the upper left. Which reminds me of a story from the old Windows 95 days. The GDI folks received a defect report from the user interface team, who backed up their report with a complicated mathematical explanation. The GDI team accepted the change request with the remark, "We ain't much fer book lernin."

Page 123 of 427 (4,268 items) «121122123124125»