• The Old New Thing

    The history of the Windows PowerToys

    • 81 Comments

    During the development of Windows 95, as with the development of any project, the people working on the project write side programs to test the features they are adding or to prototype a feature. After Windows 95 shipped, some of those programs were collected into the first edition of the Windows 95 Power Toys.

    As I recall, the first edition contained the following toys:

    CabView
    This was a handy internal tool which also served as a test of the shell folder design.

    CDAutoPlay, DeskMenu, FlexiCD, QuickRes
    These were side toys originally written by shell developers for their own personal use.

    Command Prompt Here, Explore From Here
    These were proof-of-concept toys which tested the shell command extension design.

    Round Clock
    This was a program to test regional windows.

    Shortcut Target Menu
    This was a feature idea that didn't quite make it.

    I wasn't around when the decision was made to package these toys up and ship them, so I don't know what the rule was for deciding what was PowerToy-worthy and what wasn't. Nor do I know where the name PowerToy came from. (Probably somebody just made it up because it sounded neat.)

    Upon the enormous success of the PowerToys, a second edition was developed. This time, people knew that they were writing a PowerToy, as opposed to the first edition of the PowerToys which was merely cobbled together from stuff lying around. The second edition of the Windows 95 PowerToys added FindX, Send To X, the Telephony Locator Selector, XMouse, and Tweak UI.

    Later, the kernel team released their own set of toys, known as the Windows 95 Kernel Toys. Alas, the original blurb text is not on the Microsoft downloads site, but here's an archived copy. (In reality, it was I who wrote all of the Kernel Toys, except for the Time Zone Editor, which came from the Windows NT Resource Kit. I also wrote the somewhat whimsical original blurb.)

    This was all back in the day when it was easy to put up something for download. No digital signatures, no virus checking, no paperwork. Just throw it up there and watch what happens. Today, things are very different. Putting something up for download is a complicated process with forms to fill out in triplicate and dark rooms with card readers. I wouldn't be surprised if an abandoned salt mine in Montana were somehow involved.

    Nowadays, every team at Microsoft seems to have their own PowerToys, trading on the good name of the Windows shell team who invented the whole PowerToys idea. (As far as I can tell, we don't get any royalties from other divisions calling their toys "PowerToys".) A quick check reveals the following PowerToys available for download from Microsoft; I may have missed some.

    (Plus, of course, the Windows XP PowerToys, which does come from the shell team. The Internet Explorer team originally called their stuff PowerToys, but they later changed the name to Web Accessories, perhaps to avoid the very confusion I'm discussing here.)

    What's frustrating is that since they are all called "PowerToys", questions about them tend to go to the shell team, since we are the ones who invented PowerToys. We frequently have to reply, "Oh, no, you're having a problem with the XYZ PowerToys, not the classic Windows PowerToys. We're the folks who do the classic Windows PowerToys."

    Even the blog name "PowerToys" has been co-opted by the Visual Studio team to promote their Powertoys for Visual Studio 2003.

    Some people claim that Tweak UI was written because Microsoft got tired of responding to customer complaints. I don't know where they got that from. Tweak UI was written because I felt like writing it.

    That page also says that sometimes PowerToys vanish without warning. That's true. A few years ago, all the Windows XP PowerToys were taken down so they could be given a security review. Some of them didn't survive and didn't come back. Other times, a PowerToy will be pulled because a serious bug was found. Since PowerToys are spare-time projects, it can take a very long time for a bug to get fixed, tested, and re-published. For example, the HTML Slide Show Wizard was pulled after a (somewhat obscure) data-loss bug was found. Fixing the bug itself took just a few days, but testing and filling out all the associated paperwork took six months.

    There's no moral to this story. Just a quick history lesson.

  • The Old New Thing

    How to detect programmatically whether you are running on 64-bit Windows

    • 46 Comments

    To detect programmatically whether your 32-bit program is running on 64-bit Windows, you can use the IsWow64Process function.

    Do not do as some people do and hard-code the list of 64-bit processors. You'd think that after the hard-coded list of 64-bit processors changed the first time (when x64 was added to ia64), people would have learned their lesson.

    But how do you detect programmatically from your 64-bit process whether you are running on 64-bit Windows? Easy.

    BOOL Is64BitProcessRunningOn64BitWindows()
    {
     return TRUE;
    }
    

    The fact that your 64-bit program is running at all means that you are running on 64-bit Windows! If it were a 32-bit machine, your program wouldn't be able to run.

    It's like asking the question, "Is the power on?" If there were no power, your program wouldn't be able to ask the question.

    Of course, if you want a single source code base that can be compiled both as a 32-bit program and as a 64-bit program, you have a tiny amount of work to do.

    BOOL Is64BitWindows()
    {
    #if defined(_WIN64)
     return TRUE;  // 64-bit programs run only on Win64
    #elif defined(_WIN32)
     // 32-bit programs run on both 32-bit and 64-bit Windows
     // so must sniff
     BOOL f64 = FALSE;
     return IsWow64Process(GetCurrentProcess(), &f64) && f64;
    #else
     return FALSE; // Win64 does not support Win16
    #endif
    }
    

    I threw in a branch for 16-bit programs if you're crazy enough to be still writing 16-bit Windows programs.

  • The Old New Thing

    Why did the Win64 team choose the LLP64 model?

    • 110 Comments

    Over on Channel 9, member Beer28 wrote, "I can't imagine there are too many problems with programs that have type widths changed." I got a good chuckle out of that and made a note to write up an entry on the Win64 data model.

    The Win64 team selected the LLP64 data model, in which all integral types remain 32-bit values and only pointers expand to 64-bit values. Why?

    In addition to the reasons give on that web page, another reason is that doing so avoids breaking persistence formats. For example, part of the header data for a bitmap file is defined by the following structure:

    typedef struct tagBITMAPINFOHEADER {
            DWORD      biSize;
            LONG       biWidth;
            LONG       biHeight;
            WORD       biPlanes;
            WORD       biBitCount;
            DWORD      biCompression;
            DWORD      biSizeImage;
            LONG       biXPelsPerMeter;
            LONG       biYPelsPerMeter;
            DWORD      biClrUsed;
            DWORD      biClrImportant;
    } BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;
    

    If a LONG expanded from a 32-bit value to a 64-bit value, it would not be possible for a 64-bit program to use this structure to parse a bitmap file.

    There are persistence formats other than files. In addition to the obvious things like RPC and DCOM, registry binary blobs and shared memory blocks can also be used to transfer information between processes. If the source and destination processes are different bitness, any change to the integer sizes would result in a mismatch.

    Notice that in these inter-process communication scenarios, we don't have to worry as much about the effect of a changed pointer size. Nobody in their right mind would transfer a pointer across processes: Separate address spaces mean that the pointer value is useless in any process other than the one that generated it, so why share it?

  • The Old New Thing

    Capturing the current directory from a batch file

    • 37 Comments

    Sometimes people go to great lengths to get information which is available in a much simpler way. We saw it a few days ago when we found a 200+-line C# program that could be replaced with a 90-byte batch file. Here's another example of a rather roundabout way of capturing the current directory from a batch file.

    The easy way is to use the %CD% pseudo-variable. It expands to the current working directory.

    set OLDDIR=%CD%
    .. do stuff ..
    chdir /d %OLDDIR% &rem restore current directory
    

    (Of course, directory save/restore could more easily have been done with pushd/popd, but that's not the point here.)

    The %CD% trick is handy even from the command line. For example, I often find myself in a directory where there's a file that I want to operate on but... oh, I need to chdir to some other directory in order to perform that operation.

    set _=%CD%\curfile.txt
    cd ... some other directory ...
    somecommand args %_% args
    

    (I like to use %_% as my scratch environment variable.)

    Type SET /? to see the other pseudo-variables provided by the command processor.

  • The Old New Thing

    Control how much network bandwith Automatic Updates will use

    • 50 Comments

    By default, the Background Intelligent Transfer Service (BITS) which is used by Automatic Updates will use idle network bandwidth for downloading updates. This is normally not a problem.

    One case where it can be a problem is you have a large LAN that shares a single DSL connection. BITS doesn't see that that DSL connection is shared. Consequently, each computer on the LAN will be using its idle network bandwidth to download updates and the total of all the LAN computers doing this will oversaturate the DSL connection. [Typo fixed. 31-Jan-05.]

    Another example where this can be a problem is if you have a network card that connects to a hardware firewall which in turn uses a dial-up modem to connect to the Internet. (For example, you might connect through a classic Apple AirPort which is in turn connected to a modem.) BITS sees your fast network card and can't see that there is a bottleneck further downstream. As a result, it oversaturates the dial-up connection.

    To tweak the BITS settings, you can fire up the Group Policy Editor by typing "gpedit.msc" into the Run dialog. From there, go to Computer Configuration, Administrative Templates, Network, then Background Intelligent Transfer Service. From there you can configure the maximum network bandwidth that BITS will use. You can even specify different BITS download rates based on time of day, so that it downloads more aggressively while you're sleeping, for example.

  • The Old New Thing

    The strangest way of rounding down to the nearest quarter

    • 38 Comments

    In a previous life, I wrote database software. A customer complained that one of their reports was taking an unacceptably long amount of time to generate, and I was asked to take a look at it even though it wasn't my account.

    The report was a vacation-days report, listing the number of vacation days taken and available for each employee. Vacation days accrued at a fixed rate but were granted only in quarter-day increments. For example, if you earned 15 vacation days per year and the year was 32% complete, then you had accrued 32% × 15 = 4.8 vacation days, of which 4.75 were available to use.

    The existing code to round the number of accrued days down to the nearest quarter-day went something like this:

    * assume that at this point, ACCRUED is the number
    * of accrued days.
    PRIVATE S,F
    * STR(ACCRUED,6,2) converts ACCRUED to a 6-character
    * string: 3 integer digits, a decimal point, and two
    * fractional digits.  Excess fractional digits are rounded.
    STORE STR(ACCRUED,6,2) TO S
    STORE RIGHT(S,2) TO F        && extract digits after decimal
    IF F < "25"
     F = "00"                    && 00 to 24 becomes 00
    ELSE
     IF F < "50"
      F = "25"                   && 25 to 49 becomes 25
     ELSE
      IF F < "75"
       F = "50"                  && 50 to 74 becomes 50
      ELSE
       F = "75"                  && 75 to 99 becomes 75
      ENDIF
     ENDIF
    ENDIF
    ROUNDED = VAL(LEFT(S,4) + F) && reconstruct value and convert
    

    In other words, the code converted the number to a string, extracted the digits after the decimal point, did string comparisons to figure out which quartile the fraction resided in, then created a new string with the replacement fraction and converted that string back to a number. And all this in an interpreted language.

    This code fragment was repeated each time rounding-down was needed because the language supported only 32 subroutines, and this procedure wasn't important enough to be worth kicking out one of the other existing subroutines.

    I replaced this seventeen-line monstrosity with the one-line equivalent each time it occurred, and the report ran much faster.

    (This is nowhere near the strangest way of implementing rounding. There are far worse examples.)

    Exercise: What is the one-line equivalent?

    Exercise: What is the double-rounding bug in the original code?

  • The Old New Thing

    Why do files and directories with no time/date mess up sorting in Explorer?

    • 24 Comments

    If you have a file or directory that does not have a last-modified date, you may find that it causes Explorer to sort very strangely. (How do you get a file or directory with no last-modifiied date? It's hard to do; you need the help of an external file system.) Why is this?

    As we learned earlier, a sort comparison function must impose a total order in order to produce consistent results. The problem is that Explorer's comparison function mis-handles files and directories with no last-modified date.

    To get some more of the background behind this, you need to know about so-called "simple pidls". A simple pidl is an item ID list that refers to a file or directory that does not actually exist.

    The problem is that a valid file or directory with no last-modified date looks just like one of these simple pidls becauses Explorer uses the last-modified date to distinguish whether it is manipulating a real pidl or a simple one.

    The problems with sorting occur when it comes time to decide where in the list these "real pidls that are mistaken for simple pidls" go into the sorted list. Explorer tries to keep all folders together, but if it sees a "simple pidl" it can't tell whether that item is a folder or a file (after all, something that doesn't exist is neither a file nor a folder) and it ends up producing inconsistent comparison results.

    Moral of the story: Be careful with your sort functions. If you produce inconsistent results in your sort function, you will get inconsistent results in your "sorted" output.

  • The Old New Thing

    Bringing cryptic command lines to Windows

    • 46 Comments

    The CMD.EXE batch language can be awfully cryptic, but for those who miss the richness of command lines like

    kill -1 $(ps -ef | grep inetd | grep -v grep | tr -s " " | cut -f2 -d " ")
    
    or bursts of line noise masquerading as a pipeline of "find", "sed", and "awk" processes, Microsoft Windows Services for Unix is available for free download.

  • The Old New Thing

    Alton Brown book appearance report

    • 18 Comments

    Right on schedule, Alton Brown appeared at the Elliot Bay Book Company bookstore in downtown Seattle. One of my friends wondered aloud, "Wait a second, he's promoting his cookbook. How do you do a reading from a cookbook?"

    He didn't read from his cookbook.

    To an overflow crowd that probably violated a few fire codes, Alton Brown discussed what inspired him to tackle a book on baking, riffed with the audience (he's quite funny when interacting with a crowd), then fielded questions. Alton Brown trivia:

    • At the New England Culinary Institute, he drove his teachers crazy by constantly asking the sorts of questions that he answers on his show. "What is going on chemically?" "What is the purpose of eggs in this recipe?" "Where does the water go?" They thought they were rid of him when he graduated, but AB got the last laugh: The school now gets applications which say "I want to cook like Alton Brown."
    • Why does he wear Hawaiian shirts on Good Eats? Because the material they're made from doesn't rustle against the microphone.
    • The wacko camera angles come from his background in directing television commercials. The show was originally up against The West Wing and used its irreverent style as a form of counter-programming.
    • AB claims that all the actors on the show are really production crew members brought in front of the camera. How much of this you choose to believe is up to you.
    • Each episode takes about three days to film. (Note: This doesn't count all the writing and research time.) Compare this to traditional cooking shows which film three episodes in one day!
    • The Good Eats theme is exactly ten notes long, at AB's specific request. It was allegedly inspired by the last track on the Get Shorty soundtrack CD.
    • On Iron Chef America he does not himself taste any of the dishes. Any more. He learned this lesson the hard way after trying Hiroyuki Sakai's trout ice cream.
    • Before trying any of the recipes in the book, check AB's web site for corrections. The most notorious misprint is the mysterious "aspirin" substitution on page 238. (You also have to watch out for the spelling mistakes. "Nickle"?)

    Afterwards, he signed books for ages and managed to be a good sport about it throughout. Then again, this is a book tour, after all. During that time, he's mastered the ability to sign a book and talk at the same time. I, on the other hand, am a rank amateur and couldn't even talk and watch him sign my book at the same time.

  • The Old New Thing

    Why are kernel HANDLEs always a multiple of four?

    • 27 Comments

    Not very well known is that the bottom two bits of kernel HANDLEs are always zero; in other words, their numeric value is always a multiple of 4. Note that this applies only to kernel HANDLEs; it does not apply to pseudo-handles or to any other type of handle (USER handles, GDI handles, multimedia handles...) Kernel handles are things you can pass to the CloseHandle function.

    The availability of the bottom two bits is buried in the ntdef.h header file:

    //
    // Low order two bits of a handle are ignored by the system and available
    // for use by application code as tag bits.  The remaining bits are opaque
    // and used to store a serial number and table index.
    //
    
    #define OBJ_HANDLE_TAGBITS  0x00000003L
    

    That at least the bottom bit of kernel HANDLEs is always zero is implied by the GetQueuedCompletionStatus function, which indicates that you can set the bottom bit of the event handle to suppress completion port notification. In order for this to work, the bottom bit must normally be zero.

    This information is not useful for most application writers, which should continue to treat HANDLEs as opaque values. The people who would be interested in tag bits are those who are implementing low-level class libraries or are wrapping kernel objects inside a larger framework.

Page 354 of 418 (4,180 items) «352353354355356»