History

  • The Old New Thing

    Hidden message in a T-shirt, it's been done before

    • 14 Comments

    While everybody is trying to figure out the hidden message in Joe Belfiore's T-shirt,¹ I figure I'd give you an easier puzzle.

    Here is the pattern of 0's and 1's printed on the T-shirt handed given out at the Windows 8 kick-off meeting. Because you don't have a project until you have a T-shirt.

                  001 01101110 0110
             01110011 00100000 01010111
          10 01100100 01101111 01110111 011
        0000 01001100 01101001 01110110 01100
       00000 01001001 01101110 01110100 011001
      110010 01101110           1110100 0100010
     1111000 0111000             101111 0111001
     1100101 011100               01001 0110111
      100100 0110111             110011 0010000
      010111 01101001           1100100 011011
       10111 01110011 00     0 01001100 01101
         110 01100101 00100000 01001001 011
           0 01100101 01110010 01101110 0
               000101 01111000 011100
           1 01110010 01100101 0111001001
        1001 01101110 01100100 01101111 0111
      110011 00100000 01    11 01101001 011011
     1100100 0110111            1110011 0010000
    01001100 01101                00101 00100000
    01001001 0110                  0101 01110010
    01101110 0110                  0101 01111000
    01110000 01101                10010 01100101
    0111001001010111             101110 01100100
     1101111 01110111 01110011 00100000 0101011
      101001 01101110 01100100 01101111 011101
        0011 00100000 01001100 01101001 0111
           1 00100000 01001001 01101110 0
                10010 01101110 0110
    

    The actual shirt clipped many of the digits to make the shape come out smoother. I've filled in the partial digits.

    There are at least two typos in the shirt.

    It didn't take a room full of developers long to decode the message.

    Click here to reveal the answer.

    The digits are merely the binary encoding of ASCII characters.

                  001 01101110 0110              // Windo
             01110011 00100000 01010111          // ws Wi
          10 01100100 01101111 01110111 011      // ndows
        0000 01001100 01101001 01110110 01100    //  Live
       00000 01001001 01101110 01110100 011001   //  Inte
      110010 01101110           1110100 0100010  // rnetE
     1111000 0111000             101111 0111001  // xplor
     1100101 011100               01001 0110111  // er In
      100100 0110111             110011 0010000  // dows 
      010111 01101001           1100100 011011   // Windo
       10111 01110011 00     0 01001100 01101    // ws Li
         110 01100101 00100000 01001001 011      // ve In
           0 01100101 01110010 01101110 0        // terne
               000101 01111000 011100            // tExpl
           1 01110010 01100101 0111001001        // orer  typo
        1001 01101110 01100100 01101111 0111     // indow
      110011 00100000 01    11 01101001 011011   // s Win
     1100100 0110111            1110011 0010000  // dows 
    01001100 01101                00101 00100000 // Live 
    01001001 0110                  0101 01110010 // Inter
    01101110 0110                  0101 01111000 // netEx
    01110000 01101                10010 01100101 // plore
    0111001001010111             101110 01100100 // r[?nd typo
     1101111 01110111 01110011 00100000 0101011  // ows L
      101001 01101110 01100100 01101111 011101   // indow
        0011 00100000 01001100 01101001 0111     // s Liv
           1 00100000 01001001 01101110 0        // e Int
                10010 01101110 0110              // ernet
    

    ¹ Looks like they figured it out.

  • The Old New Thing

    How did the scopes for the CryptProtectMemory function end up in a strange order?

    • 4 Comments

    A few weeks ago, I left an exercise: Propose a theory as to why the names and values of the scopes for the Crypt­Protect­Memory function are the way they are.

    I didn't know the answer when I posed the exercise, but I went back and dug into it.

    The Crypt­Protect­Memory function started out as an internal function back in Windows 2000, and when originally introduced, there were only two scopes: Within a process and cross-process. The Flags parameter therefore defined only a single bit, leaving the other bits reserved (must be zero). If the bottom bit was clear, then the memory was protected within a process; if the bottom bit was set, then the memory was protected across processes.

    Later, the team realized that they needed to add a third scope, the one that corresponds to CRYPT­PROTECT_SAME_LOGON. They didn't want to make a breaking change for existing callers, but they saw that they could retarget what used to be a Flags parameter as an Options parameter, and they added the new scope as a third option.

    The numeric values remained unchanged, which meant that the new function was backward-compatible with existing callers.

    Bonus chatter: Commenter sense is correct that SAME_LOGON can be used by a service while impersonating the client, however it is not the case that the scope can be larger when impersonating a remote user. The memory block returned by the Crypt­Protect­Memory function can be decrypted only on the same machine that encrypted it, and only as long as the machine has not been rebooted.

  • The Old New Thing

    What was the starting point for the Panther Win32 kernel?

    • 21 Comments

    When I presented a list of cat-related code names from Windows 95, commenter dave wanted to know whether the Panther kernel was derived from the 32-bit DOS kernel or the Windows/386 kernel.

    Neither.

    Here's the table again, with some more columns of information:

    Component Code Name Based on Fate
    16-bit DOS kernel Jaguar MS-DOS 5 Morphed into Windows 95 boot loader / compatibility layer
    32-bit DOS kernel Cougar Win386 kernel Morphed into VMM32
    Win32 kernel Panther Windows NT kernel Cancelled
    User interface Stimpy Windows 3.1 user interface Became the Windows 95 user interface

    The original idea for the Jaguar and Cougar projects was to offer a 16-bit MS-DOS environment that could be "kicked up a notch" to a 32-bit protected-mode MS-DOS environment, with virtual memory and multiple virtual machines. They used the MS-DOS 5 and Win386 kernels as starting points. (Why wasn't Jaguar based on MS-DOS 6.0? For the same reason NASA didn't use the Space Shuttle to rescue the Apollo 13 astronauts.) This project as originally envisioned was cancelled, but the work was not lost. The projects took on new life as the Windows 95 boot loader / compatibility layer and as the Windows 95 virtual machine manager, respectively.

    The idea for the Panther project was to start with the existing Windows NT kernel and strip it down to run in 4MB of RAM. This project did not pan out, and it was cancelled outright. It was replaced with a Win32 kernel written from scratch with the 4MB limit in mind.

    The Stimpy project survived intact and became the Windows 95 user interface.

    I doubt the code name was the reason, but it's interesting that the ferocious cats did not carry out their original missions, but the dim-witted cat did.

  • The Old New Thing

    Why are there both TMP and TEMP environment variables, and which one is right?

    • 49 Comments

    If you snoop around your environment variables, you may notice that there are two variables that propose to specify the location of temporary files. There is one called TMP and another called TEMP. Why two? And if they disagree, then who's right?

    Rewind to 1973. The operating system common on microcomputers was CP/M. The CP/M operating system had no environment variables. That sounds like a strange place to start a discussion of environment variables, but it's actually important. Since it had no environment variables, there was consequently neither a TMP nor a TEMP environment variable. If you wanted to configure a program to specify where to put its temporary files, you needed to do some sort of program-specific configuration, like patching a byte in the executable to indicate the drive letter where temporary files should be stored.

    (My recollection is that most CP/M programs were configured via patching. At least that's how I configured them. I remember my WordStar manual coming with details about which bytes to patch to do what. There was also a few dozen bytes of patch space set aside for you to write your own subroutines, in case you needed to add custom support for your printer. I did this to add an "Is printer ready to accept another character?" function, which allowed for smoother background printing.)

    Move forward to 1981. The 8086 processor and the MS-DOS operating system arrived on the scene. The design of both the 8086 processor and the MS-DOS operating system were strongly inspired by CP/M, so much so that it was the primary design goal that it be possible to take your CP/M program written for the 8080 processor and machine-translate it into an MS-DOS program written for the 8086 processor. Mind you, the translator assumed that you didn't play any sneaky tricks like self-modifying code, jumping into the middle of an instruction, or using code as data, but if you played honest, the translator would convert your program.

    (The goal of allowing machine-translation of code written for the 8080 processor into code written for the 8086 processor helps to explain some of the quirks of the 8086 instruction set. For example, the H and L registers on the 8080 map to the BH and BL registers on the 8086, and on the 8080, the only register that you could use to access a computed address was HL. This is why of the four basic registers AX, BX, CX, and DX on the 8086, the only one that you can use to access memory is BX.)

    One of the things that MS-DOS added beyond compatibility with CP/M was environment variables. Since no existing CP/M programs used environment variables, none of the first batch of programs for MS-DOS used them either, since the first programs for MS-DOS were all ported from CP/M. Sure, you could set a TEMP or TMP environment variable, but nobody would pay attention to it.

    Over time, programs were written with MS-DOS as their primary target, and they started to realize that they could use environment variables as a way to store configuration data. In the ensuing chaos of the marketplace, two environment variables emerged as the front-runners for specifying where temporary files should go: TEMP and TMP.

    MS-DOS 2.0 introduced the ability to pipe the output of one program as the input of another. Since MS-DOS was a single-tasking operating system, this was simulated by redirecting the first program's output to a temporary file and running it to completion, then running the second program with its input redirected from that temporary file. Now all of a sudden, MS-DOS needed a location to create temporary files! For whatever reason, the authors of MS-DOS chose to use the TEMP variable to control where these temporary files were created.

    Mind you, the fact that COMMAND.COM chose to go with TEMP didn't affect the fact that other programs could use either TEMP or TMP, depending on the mood of their original author. Many programs tried to appease both sides of the conflict by checking for both, and it was up to the mood of the original author which one it checked first. For example, the old DISKCOPY and EDIT programs would look for TEMP before looking for TMP.

    Windows went through a similar exercise, but for whatever reason, the original authors of the Get­Temp­File­Name function chose to look for TMP before looking for TEMP.

    The result of all this is that the directory used for temporary files by any particular program is at the discretion of that program, Windows programs are likely to use the Get­Temp­File­Name function to create their temporary files, in which case they will prefer to use TMP.

    When you go to the Environment Variables configuration dialog, you'll still see both variables there, TMP and TEMP, still duking it out for your attention. It's like Adidas versus Puma, geek version.

  • The Old New Thing

    Why did the original code for FIND.COM use lop as a label instead of loop?

    • 4 Comments

    A few years ago, I left you with an exercise: Given the code

            mov     dx,st_length            ;length of the string arg.
            dec     dx                      ;adjust for later use
            mov     di, line_buffer
    lop:
            inc     dx
            mov     si,offset st_buffer     ;pointer to beg. of string argument
    
    comp_next_char:
            lodsb
            cmp     al,byte ptr [di]
            jnz     no_match
    
            dec     dx
            jz      a_matchk                ; no chars left: a match!
            call    next_char               ; updates di
            jc      no_match                ; end of line reached
            jmp     comp_next_char          ; loop if chars left in arg.
    

    why is the loop label called lop instead of loop?

    The answer is that calling it loop would create ambiguity with the 8086 instruction loop.

    Now, you might say (if your name is Worf), that there is no ambiguity. "Every line consists of up to four things (all optional). A label, an instruction/pseudo-instruction, operands, and comments. The label is optionally followed by a colon. If there is no label, then the line must start with whitespace."

    If those were the rules, then there would indeed be no ambiguity.

    But those aren't the rules. Leading whitespace is not mandatory. If you are so inclined, you can choose to begin your instructions all in column zero.

    mov dx,st_length
    dec dx
    mov di, line_buffer
    lop:
    inc dx
    mov si,offset st_buffer
    comp_next_char:
    lodsb
    cmp al,byte ptr [di]
    jnz no_match
    dec dx
    jz a_matchk
    call next_char
    jc no_match
    jmp comp_next_char
    

    It's not recommended, but it's legal. (I have been known to do this when hard-coding breakpoints for debugging purposes. That way, a search for /^int 3/ will find all of my breakpoints.)

    Since you can put the opcode in column zero, a line like this would be ambiguous:

    loop ret
    

    This could be parsed as "Label this line loop and execute a ret instruction." Or it could be parsed as "This is an unlabeled line, consisting of a loop instruction that jumps to the label ret."

    Label Opcode Operand
    loop ret
    – or –
    loop ret

    Disallowing instruction names as labels or macros or equates is the simplest way out of this predicament. Besides, you probably shouldn't be doing it anyway. Imagine the havoc if you did

    or equ and
    
  • The Old New Thing

    What was the relationship between Outlook and Outlook Express?

    • 23 Comments

    Brian wonders whether project Stimpy became Outlook Express.

    As noted in the article, projects Ren and Stimpy were merged into a single project, which became Outlook. You could say that Stimpy became Outlook, too.

    Outlook Express (code name Athena) was originally known as Internet Mail and News. This was back in the day when the cool, hip thing for Web browsers to do was to incorporate as many Internet client features as possible. In the case of Internet Mail and News, this was POP (mail) and NNTP (news).

    After Outlook became a breakout hit, the Internet Mail and News project was renamed to Outlook Express in an attempt to ride Outlook's coattails. It was a blatant grab at Outlook's brand awareness. (See also: SharePoint Workspaces was renamed OneDrive for Business; Lync was renamed Skype for Business.)

    The decision to give two unrelated projects the same marketing name created all sorts of false expectations, because it implied that Outlook Express was a "light" version of Outlook. People expected that Outlook Express could be upgraded to Outlook, or that Outlook Express and Outlook data files were compatible with each other.

    Code name reuse is common at Microsoft, and for a time, the code names Ren and Stimpy were popular, especially for projects that were closely-related. (As I vaguely recall, there was a networking client/server project that called the server Ren and the client Stimpy. But I may be misremembering, and Ren and Stimpy may just have been the names of the two source code servers.) You may have heard the names Ren and/or Stimpy in reference to some other projects. Doesn't mean that your projects are related to any others with the same name.

  • The Old New Thing

    Flaw reported in Windows 95

    • 24 Comments

    One of my colleagues ran across this old news clipping from 20 years ago today.

    Flaw reported in Windows 95

    THE ASSOCIATED PRESS

    SAN MATEO, Calif. — Microsoft Corp.'s long-awaited Windows 95 operating system has a flaw that can freeze up computers when running certain applications, InfoWorld magazine said Friday.

    The company is aware of the problem but is shipping 450,000 anyway as part of a preview program, the magazine said.

    "I fear that unless Microsoft goes back to the drawing board on this operating system, only light users will get anything out of it," said Nicholas Petreley, the magazine's executive editor.

    He said the system's inability to handle several types of sophisticated applications at the same time made it questionable for business use.

    I can't find a copy of the original InfoWorld article online; all I can find are citations to it, like this one and this one.

    The clipping had a handwritten note attached:

    Bob,
    You guys may want to respond to this.
    Mom

    The report was shortly followed by a rebuttal from Windows Magazine, pointing out that this was a beta release, it is not unusual that an unfinished product has bugs, and that a similar bug in an earlier beta was fixed within two weeks.

    ZOMG! A beta product has a bug!

    I found it cute that my colleague's mother chose to bring this article to her son's attention.

  • The Old New Thing

    Setting up a new computer often results in leftover slot covers, so what do you do with the slot covers?

    • 30 Comments

    When I joined Microsoft, I had a brand new computer waiting for me. One of the rites of passage for new employees is setting up their computer. A colleague helped me out with this effort, and one of the steps he performed was installing the network card. (Back in the day, network adapters were not integrated into the motherboard. If you wanted one, you had to buy an add-on card.)

    Now, when you install a network card, it occupies a slot, and you need to remove the corresponding slot cover because the card comes with its own integrated slot cover. When my colleague removed the old slot cover from the computer, he didn't just toss it into the garbage. He folded it back on itself with the tab on the top, like this: ᔪ

    What the heck was that all about?

    He didn't give me time to ask the question because he immediately walked over to my office door, pulled it all the way open, and then jammed the doodad under the door. The tab at the top caught the door, and the angled bottom part dug into the carpet, holding the door open:

    In other words, he took the slot cover and converted it into a doorstop.

    Thereafter, I noticed that all of my coworkers used slot covers to hold their office doors open. It was part of the team's tribal knowledge.

    (This trick is lost to history not only because computers nowadays come with all the peripherals you would typically need, but also because the new office doors are not spring-loaded.)

  • The Old New Thing

    Why is there a BSTR cache anyway?

    • 25 Comments

    The Sys­Alloc­String function uses a cache of BSTRs which can mess up your performance tracing. There is a switch for disabling it for debugging purposes, but why does the cache exist at all?

    The BSTR cache is a historical artifact. When BSTRs were originally introduced, performance tracing showed that a significant chunk of time was spent merely allocating and freeing memory in the heap manager. Using a cache reduced the heap allocation overhead significantly.

    In the intervening years, um, decades, the performance of the heap manager has improved to the point where the cache isn't necessary any more. But the Sys­Alloc­String people can't get rid of the BSTR because so many applications unwittingly rely on it.

    The BSTR cache is now a compatibility constraint.

  • The Old New Thing

    My pants are fancy!

    • 13 Comments

    During the development of Windows, the User Research team tried out an early build of some proposed changes on volunteers from the general community. During one of the tests, they invited the volunteer to just play around with a particular component, to explore it the way they would at home.

    The usability subject scrolled around a bit, admired the visuals, selected a few things, and then had an idea to try to customize the component. He fiddled around a bit and quickly discovered the customization feaure.

    To celebrate his success, he proudly announced in a sing-song sort of way, "My pants are fancy!"

    That clip of a happy usability study participant gleefully announcing "My pants are fancy!" tickled the team's funny bone, and the phrase "My pants are fancy" became a catch phrase.

Page 1 of 51 (507 items) 12345»