September, 2008

  • The Old New Thing

    2008 Q3 link clearance: Microsoft blogger edition

    • 5 Comments

    It's that time again: Sending some link love to my colleagues.

    [Raymond is currently away; this message was pre-recorded.]

  • The Old New Thing

    When computer programmers dabble in economics: Buying prepaid lunch vouchers

    • 15 Comments

    Several years ago, the Microsoft cafeterias phased out their prepaid lunch voucher system. Under the new system, you "load up" your security badge with money (either by paying cash at any register or by having the amount deducted from your paycheck) and then swipe your badge at card readers installed at each register. But in the old days, the system operated manually.

    Under the old system, you paid $25 cash for a voucher which, when folded in half, was about the size of a business card. On the card were boxes with various denominations ($1, 25¢, 10¢, 5¢), and when you bought something with your voucher card, the person at the register used a pen to X out the various boxes to void them. For example, if you bought something for $3.50, the person at the register would cross off three $1 boxes and two 25¢ boxes. (And since I know people will ask even though it's totally irrelevant to the story: Yes, there were provisions for "making change", for example, if you had four 25¢ boxes remaining and you bought something for 90¢, but they were rarely needed.)

    Yes, this system was easily hacked, but nobody did. Partly because the fact that it was so easy to hack removed the challenge, but mostly because we try not to hire dishonest people.

    When you bought one of these voucher cards, you receive $27 in credit for your $25 prepayment. The security badge payment system doesn't have this "cash bonus" feature, and when the cafeteria people announced that voucher card system was being phased out, one of my colleagues sat down and, making various assumptions on the time value of money, how much money a typical lunch cost, and possibly even the current price of energy on the spot market for all I know, calculated the optimum number of voucher cards to purchase in order to maximize the benefit from the cash bonus.

    As I recall, the calculations determined that seventeen voucher cards was the optimum.

    [Raymond is currently away; this message was pre-recorded.]

  • The Old New Thing

    Meet the authors: Mario Hewardt and Daniel Pravat, authors of Advanced Windows Debugging

    • 8 Comments

    My colleague Mario Hewart just let me know that he and Daniel Pravat will be presenting at the PDC pre-con. In case you don't recognize the names, they're the authors of Advanced Windows Debugging, a book which I reviewed late last year.

    So if you want to get your debugging tips directly from the source, you know where to go.

    Besides, Mario speaks Swedish, so he's already awesome by default.

    [Raymond is currently away; this message was pre-recorded.]

  • The Old New Thing

    Anybody can make up a generic mapping

    • 17 Comments

    Each component that uses ACLs to control access has its own idea of what GENERIC_READ, GENERIC_WRITE, and GENERIC_EXECUTE mean. It's not like there's a master list that somebody can make that lists them all, because I can make up a new one right here. Watch me:

    #define GIZMO_QUERY_STATUS   0x0001
    #define GIZMO_QUERY_MEMBERS  0x0002
    #define GIZMO_START          0x0004
    #define GIZMO_STOP           0x0008
    #define GIZMO_ADD_CLIENT     0x0010
    #define GIZMO_REMOVE_CLIENT  0x0020
    
    #define GIZMO_GENERIC_READ  (STANDARD_RIGHTS_READ | \
                                 GIZMO_QUERY_STATUS | \
                                 GIZMO_QUERY_MEMBERS)
    #define GIZMO_GENERIC_READ  (STANDARD_RIGHTS_READ | GIZMO_QUERY_STATUS)
    #define GIZMO_GENERIC_WRITE (STANDARD_RIGHTS_WRITE | \
                                 GIZMO_ADD_CLIENT | \
                                 GIZMO_REMOVE_CLIENT)
    #define GIZMO_GENERIC_EXECUTE (STANDARD_RIGHTS_EXECUTE | \
                                 GIZMO_START | \
                                 GIZMO_STOP)
    #define GIZMO_ALL_ACCESS    (STANDARD_RIGHTS_REQUIRED | \
                                 GIZMO_QUERY_STATUS | \
                                 GIZMO_QUERY_MEMBERS | \
                                 GIZMO_START | \
                                 GIZMO_STOP | \
                                 GIZMO_ADD_CLIENT   | \
                                 GIZMO_REMOVE_CLIENT)
    
    GENERIC_MAPPING GizmoGenericMapping = {
        GIZMO_GENERIC_READ,
        GIZMO_GENERIC_WRITE,
        GIZMO_GENERIC_EXECUTE,
        GIZMO_ALL_ACCESS,
    };
    

    It's not just kernel objects that use ACLs. Anybody who wants to set up permissions can use ACLs to control access. For example, the file server service uses ACLs to control which users can create new file shares, which users can view printer properties, which users can connect to administrative shares, all that stuff. There is no kernel object that these access masks apply to; they merely control who can do what with the service.

    In that example above, a "gizmo" might be some sort of chat room with a member list. Some users may have permission to add and remove other members from the chat room; others have permission to open the chat room or shut it down. When a client wants to perform an operation on the chat room, the program obtains the security descriptor for the chat room and calls AccessCheck to see whether the caller has permission to perform the operation.

    This is a totally artificial example. My point is that anybody can make up access bits and use them to control access to some sort of shared resource. That shared resource might be something you think of as a "real object" like a file or a process, but it could be some sort of purely virtual construction like a chat room or a file share. Even if some sort of "complete list" were developed, anybody working in a basement can add a new one, and then your complete list is incomplete.

    Bonus chatter: One of my colleagues points out that the mandatory integrity mechanism does have implications for generic mappings. I don't even understand that sentence, but there it is for you to ponder.

    [Raymond is currently away; this message was pre-recorded.]

  • The Old New Thing

    ERRORLEVEL is not %ERRORLEVEL%

    • 15 Comments

    The command interpreter cmd.exe has a concept known as the error level, which is the exit code of the program most recently run. You can test the error level with the IF ERRORLEVEL command:

    IF ERRORLEVEL 1 ECHO error level is 1 or more
    

    <sidebar>
    The IF ERRORLEVEL n test succeeds if the error level is n or more. This was presumably because there were programs that expressed different degrees of failure with higher and higher exit codes. For example, the diff program has three exit codes: 0 means the files are the same; 1 means the files are different; 2 means that something terrible happened. There are also programs that use an exit code of zero to mean success and anything else to mean failure.
    </sidebar>

    In addition to this internal state, you can, if you wish, create an environment variable with the name ERRORLEVEL, in the same way that you can create an environment variable called FRED. But, as with FRED, that variable won't have any effect on the error level.

    rem this next command sets the error level to zero
    CMD /C EXIT 0
    set ERRORLEVEL=1
    if ERRORLEVEL 1 echo Does this print?
    

    The message is not printed because the ERRORLEVEL environment variable has no effect on the error level. It's just a variable whose name happens to coincide with a command processor concept.

    set BANKBALANCE=$1,000,000.00
    

    "Hey, when I tried to withdraw the money, I got an insufficient funds error. What am I doing wrong?"

    Now, it does happen to be the case that if command extensions are enabled and you say %ERRORLEVEL%, then the command processor first looks for an environment variable called ERRORLEVEL, and if it can't find one, then it replaces %ERRORLEVEL% with the current value of the internal error level value. It's a fallback step, in the same way that your neighbor is a fallback delivery location if you aren't home. If you file a change-of-address form for yourself, that doesn't affect packages sent to your neighbor.

    The same behavior can be seen with %CD%: If you did not explicitly set an environment variable called CD, then %CD% expands to the command processor's current directory. But you can't change directories by saying set CD=C:\Windows.

    I can think of a few reasons why this feature may have been added.

    • So you can include the error level in a log file:
      ECHO error level is %ERRORLEVEL%>logfile
    • So you can perform other types of tests against the error level, for example, to perform an equality test:
      IF %ERRORLEVEL% EQU 1 echo Different!

    But I'm digressing. My point for today is that the error level is not the same as the ERRORLEVEL environment variable.

  • The Old New Thing

    The description of my 2008 PDC talk is wrong

    • 28 Comments

    The title is mostly okay, but the description is wrong. Thanks to the power of web scripting, I can't actually link to my talk; I can just link to the main session page, and then you'll have to go searching for it. (Maybe there's a direct link but I can't find it.)

    The title Windows 7: Deep Dive - What's New with Win32's user32 and comctl32 is mostly okay. Except that it's not Windows 7, because I don't talk about the future; I talk about the past. So it's really Windows Vista: Deep Dive - What Was New with Win32's user32 and comctl32.

    The description needs work, though. I submitted an updated version just last night, but who knows if they'll approve it. The description I had in mind goes more like this:

    This talk focuses on the lowest level user interface components (user32, comctl32) that appear in almost every Windows application. You'll learn about "recent" changes and enhancements in these subsystems, plus be subjected to some philosophical musings on how foreground activation is like love. (No really, it will actually help you write better software.)
  • The Old New Thing

    Even if a function doesn't do anything, you still have to call it if the documentation says so, because it might do something tomorrow

    • 38 Comments

    If the documentation says that you have to call a function, then you have to call it. It may be that the function doesn't do anything, but that doesn't prevent it from doing something in the future.

    Today's example is the function GetEnvironmentStrings, which returns you all the environment variables of the current process in a single block, which you can then study at your leisure. When you're finished, you're supposed to call FreeEnvironmentStrings. That's what the documentation says, and if you did that, then you're in good shape.

    However, some people noticed that on Windows NT 4, the Unicode version of the FreeEnvironmentStrings function didn't do anything. In other words, the Unicode environment block didn't need to be freed. When you called GetEnvironmentStrings, the kernel just returned you a raw pointer to the real live environment strings (which, since this is Windows NT, are kept in Unicode internally). Since nothing was allocated, there was nothing to free.

    The problem with this technique was that if somebody called SetEnvironmentVariable in the meantime, the environment block changed out from under the caller of GetEnvironmentStrings.

    Oops.

    To fix this, the GetEnvironmentStrings function was changed to return a copy of the environment block even if you call the Unicode version. The corresponding Unicode FreeEnvironmentStrings function frees that environment copy.

    Programs that followed the specification and called FreeEnvironmentStrings (even though it didn't do anything up until now) were in good shape. Their call to FreeEnvironmentStrings now frees the memory, and all is right with the world.

    Programs that coded to the implementation rather than the specification are now in a world of hurt. If they simply skipped the "useless" call to FreeEnvironmentStrings, they will now find themselves leaking memory. On the other hand, if they gave lip service to FreeEnvironmentStrings by calling it, but using the memory anyway, they will find themselves accessing invalid heap memory, and all sorts of havoc can ensue.

    There's sometimes a reason for the rules that seem stupid at first glance. ("Call this function that doesn't do anything.") Changes to the implementation may make them less stupid in the future.

    (Credit goes to my colleague Neill Clift for providing the information that led to today's article.)

  • The Old New Thing

    When attending a training session on how not to mess up your life, try not to mess up your life

    • 20 Comments

    Like the NFL, the NBA has its own Rookie Transition Program for introducing new players to important issues such as life skills, money management, dealing with the media, and the importance of character and image in avoiding public embarrassment. Apparently it took longer than usual for these lessons to sink in for Mario Chalmers and Darrell Arthur, since they were caught in their hotel room with two unspecified women, and security claimed to have smelled marijuana although none was found. They were fined $20,000 apiece, and a fellow player was fined $50,000 for his involvement and failure to cooperate with the investigation.

    The two players also were ordered to go through the training a second time. Maybe this time, they'll learn something.

    Follow-up: ESPN has a summary of events. Fire alarm. Refusing to let security into the room. Repeated toilet flushing. Gotta love it.

  • The Old New Thing

    How do I change the size of my desktop icons?

    • 27 Comments

    Occasionally, somebody asks how to change the size of the desktop icons, not because they want to change the size from the default, but rather because they somehow turned into giant marshmallow men and they want to get the default size back.

    There are two ways to change the size of the desktop icons on Windows Vista:

    • Click on the desktop, then hold the Control key while rotating the mouse wheel.
    • Right-click on the desktop and choose an icon size from the View menu.

    When people get into this state where the desktop icons are gargantuan, it's usually due to a mouse that went berserk thanks to some sort of hardware problem such as a loose connection. By the time the hardware problem is fixed, the mouse has clicked and twirled randomly all over the screen, causing all sorts of havoc.

  • The Old New Thing

    Microspeak: Space delivery

    • 14 Comments

    As I noted in an earlier entry of Microspeak, the real estate department here has their own weird jargon. Today's phrase is "delivering space":

    Listed below is the schedule for delivery of space over the next twelve months.

    Translation: "Listed below is the schedule for when new office space will become ready for use over the next twelve months."

Page 1 of 4 (33 items) 1234