• The Old New Thing

    For Honor, For Excellence, For Pizza

    • 18 Comments

    Hacker News member citizenlow recalls the time I went over after hours to help out the Money team debug a nasty kernel issue. They were running into mysterious crashes during their stress testing and asked for my help in debugging it.

    I helped out other teams quite a bit, like writing a new version of Dr. Watson for the Windows 98 team or writing a new version of the MSConfig tool based on a sketch on a bar napkin. And for a time, I followed the official policy for moonlighting to make sure everybody understood that I was doing work outside the boundaries of my official job duties.

    When the Money folks asked me for help, I told them that before I could help them, they would have to help me fill out some paperwork.

    • Who will you be working for? Microsoft Corporation.
    • Where will you be doing the work? Office XX/YYYY on Microsoft Redmond Campus.
    • When will the work begin and end? Begin on YYYY/MM/DD at 5pm, ending YYYY/MM/DD at 11pm.
    • How much will you be paid for this work?

    The Money folks were not sure how to answer that last question, since they didn't have any formal budget or procedures for hiring an outside consultant, much less any procedures for hiring one from inside the company.

    I told them, "Just write One slice of pizza."

    Nobody from the Personnel department seemed to notice the odd circumstances of this moonlighting request; they simply rubber-stamped it and put it in my file.

    The crash, it turns out, was in Windows itself. There was a bug in the special compiler the Languages team produced to help build certain components of Windows 95 which resulted in an incorrect address computation under a particularly convoluted boundary condition. The Money folks had merely stumbled across this bug as part of their regular testing. I notified the appropriate people, and the Windows team applied a workaround in their code to tickle the compiler into generating the correct code.

    As I recall, the pizza was just fine. It was just your average delivery pizza, nothing gourmet or anything. Not that it had to be, because I wasn't there for the pizza.

  • The Old New Thing

    "Super" watch, episode 2

    • 5 Comments

    Not just "super exciting" but "super-super-exciting". (But at least he's not super super super excited.) I don't consider this super encouraging.

    Episode 1.

  • The Old New Thing

    News flash: Work-at-home job offers are mostly just scams

    • 8 Comments

    McClatchy Newspapers discovers, to everyone's surprise, that work-at-home job offers are mostly just scams. Of course, this is something Rob Cockerham discovered years ago. (He also has a rundown of all his articles on the subject, in case you haven't gotten enough.)

  • The Old New Thing

    The walls of my friend's house sometimes randomly got corrupted

    • 16 Comments

    One evening, I had a series of three dreams. In each one, I visited an unusual home.

    In the third dream, I visited the home of a friend of mine. He lived in a white stucco split-level, a stereotypical suburban home. What made the house interesting was that if you did things just right, dark dots would appear on the wall and slowly consume it.

    My friend explained, "This house is running a very old build of DirectX, and sometimes it just does that."

    We set up a repro and calculated that when the dots appeared, stack usage was exactly 5124 bytes. This was a 16-bit house, and the stack overflow into the heap caused a return address to be changed to point into the DirectDraw flood fill function.

    When I told my friend about this strange dream, he quipped, "I've since then upgraded to a 64-bit house."

  • The Old New Thing

    Answers to exercises

    • 0 Comments

    Exercise: Explain why we used 0x7FFF to represent infinite height.

    Answer: Commenter "Reiko" got this right. 0x7FFF is the maximum integer coordinate supported by Windows 95, 98 and Me.

    Exercise: Explain the line rcWindow.bottom += rcTemp.top.

    Answer: The more precise way of writing the line would have been

        rcWindow.bottom += (rcTemp.top - rcWindow.top) - (0 - rcWindow.top);
    
    The first term is the amount of non-client space consumed at the top of the window. The second term is the amount of non-client space consumed at the top of the window, taking wrapping into account. The difference, therefore is the amount by which AdjustWindowRectEx needs to be adjusted. But the two instances of rcWindow.top cancel out, leaving just rcTemp.top.
  • The Old New Thing

    The format of bitmap resources

    • 10 Comments

    Another in a sporadic series on the format of Win32 resources.

    Here's a question from a customer:

    I'm noticing some strange behavior: When I call LoadResource then LockResource on an embedded bitmap, the data being returned by LockResource is not a properly formatted bitmap. The data is missing the BITMAPFILEHEADER, but the rest of the file is there. SizeOfResource also states that the bitmap resource is 14 bytes smaller than it actually is. 14 bytes happens to be equal to sizeof(BITMAPFILEHEADER).

    However, if I load the bitmap directly using LoadBitmap, everything works fine. If I look at the resource using Visual Studio, the Bitmap displays correctly and the binary data correctly includes the BITMAPFILEHEADER.

    Anyone have any ideas as to why LoadResource is not correctly returning the BITMAPFILEHEADER?

    Amusingly, a change to the word order changes the question to its own answer: LoadResource is correctly not returning the BITMAPFILEHEADER.

    In other words, LoadResource is not stripping off the BITMAPFILEHEADER: rc.exe is.

    The format of bitmap resources are pretty simple. They are just a bitmap file with the BITMAPFILEHEADER stripped off. Because it's just the file header, the thing tacked onto the front when saved as a file. It's not part of the bitmap itself. For example, if you are using a BITMAPINFOHEADER-formatted bitmap, then the resource format is a BITMAPINFOHEADER followed by the pixels.

    I can't explain why Visual Studio is showing you a BITMAPFILEHEADER that doesn't exist. They're probably trying to reduce confusion for people who don't know the format of bitmap resources and wonder why the binary data doesn't match their .bmp file. Of course, in so doing, they end up creating confusion for people who do know the format of bitmap resources, or—as happened here—people who don't know the format of bitmap resources and think that the LoadResource function is messing with their bitmaps.

    (For the record, the LoadResource function doesn't mess with bitmaps, icons, menus, or whatever. It just returns the raw binary data of a Win32 resource. It doesn't know the internal format of those resources any more than the file system knows the internal format of a Quicken data file or a shortcut file.)

  • The Old New Thing

    Why doesn't the MoveWindow function generate the WM_GETMINMAXINFO message?

    • 16 Comments

    Commenter Phil Quirk asks why calling MoveWindow does not result in a WM_GETMINMAXINFO message being sent to validate the moved window size.

    Well, because you moved it after all. You're being trusted to respect your own rules. After all, if you didn't want the window to be wider than 200 pixels, you shouldn't have passed nWidth=300, right?

    The WM_GETMINMAXINFO message is for obtaining minimum and maximum sizing information when the sizes were chosen by a means outside the application's control, such as when you said "I'll let you choose the window size (CW_USEDEFAULT)" or when the user grabbed the corner of the window and started dragging it around. But if you yourself changed the window size, then the window manager assumes that you know what you're doing.

    If you don't trust yourself to follow your own rules, you can intercept the attempt to change the window size by handling the WM_WINDOWPOSCHANGING message.

  • The Old New Thing

    When will GetSystemWindowsDirectory return something different from GetWindowsDirectory?

    • 30 Comments

    Most of the time, the Get­Window­Directory returns the Windows directory. However, as noted in the documentation for Get­System­Windows­Directory:

    With Terminal Services, the Get­System­Windows­Directory function retrieves the path of the system Windows directory, while the Get­Windows­Directory function retrieves the path of a Windows directory that is private for each user. On a single-user system, Get­System­Windows­Directory is the same as Get­Windows­Directory.

    What's going on here, and how do I test this scenario?

    When Terminal Services support was being added to Windows NT 4.0 in the mid 1990's, the Terminal Services team discovered that a lot of applications assumed that the computer was used by only one person, and that that person was a local administrator. This was the most common system configuration at the time, so a lot of applications simply assumed that it was the only system configuration.

    On the other hand, a Terminal Server machine can have a large number of users, including multiple users connected simultaneously, and if the Terminal Services team took no special action, you would have found that most applications didn't work. The situation "most applications didn't work" tends not to bode well for adoption of your technology.

    Their solution was to create a whole bunch of compatibility behaviors and disable them if the application says, "Hey, I understand that Terminal Server machines are different from your average consumer machine, and I know what I'm doing." One of those compatibility behaviors is to make the Get­Windows­Directory function return a private writable directory rather than the real Windows directory, because old applications assumed that the Windows directory was writable, and they often dumped their private configuration data there.

    The signal to disable compatibility behaviors is the IMAGE_DLLCHARACTER­ISTICS_TERMINAL_SERVER_AWARE flag in the image attributes of the primary executable. You tell the linker that you want this flag to be set by passing the /TSAWARE:YES parameter on the command line. (At some point, the Visual Studio folks made /TSAWARE:YES the default for all new projects, so you are probably getting this flag set on your files without even realizing it. You can force it off by going to Configuration Properties, and under Linker, then System, change the "Terminal Server" setting to "Not Terminal Server Aware".)

    Note that only the flag state on the primary executable has any effect. Setting the flag on a DLL has no effect. (This adds to the collection of flags that are meaningful only on the primary executable.)

    The other tricky part is that the Terminal Server compatibility behaviors kick in only on a Terminal Server machine. The way you create a Terminal Server machine has changed a lot over the years, as has the name of the feature.

    • In Windows NT 4.0, it was a special edition of Windows, known as Windows NT 4.0 Terminal Server Edition.
    • In Windows 2000, the feature changed its name from Terminal Server to Terminal Services and became an optional server component rather than a separate product. You add the component from Add/Remove Programs.
    • In Windows Server 2003 and Windows Server 2008, you go to the Configure Your Server Wizard and add the server rôle "Terminal Server."
    • In Windows Server 2008 R2, the feature changed its name again. The instructions are the same as in Windows Server 2008, but the rôle name changed to "Remote Desktop Services".
    • In Windows Server 2012, the feature retained its name but became grouped under the category "Virtual Desktop Infrastructure." This time, you have to enable the rôle server "Remote Desktop (RD) Session Host."

    Terminal Services is the Puff Daddy of Windows technologies. It changes its name every few years, and you wonder what it will come up with next.

  • The Old New Thing

    I totally presented to an executive the wrong way

    • 10 Comments

    Some time ago, Gray Knowlton wrote an article on how to present to an executive.

    As you might have guessed, I've done it completely the wrong way.

    Many years ago, I was part of a group presenting to a senior-level executive. I was the one who wrote the document establishing the background for the topic and laying out the various options with their pros and cons. I wasn't the one doing the actual presenting, but I was asked to attend anyway, just in case the senior executive had a question that the presenters couldn't answer.

    For the duration of the meeting, I sat in the back and knitted.

    As it turns out, I wasn't needed. But at least I got some knitting done.

    (I was commended for the quality of the document I had written, so don't think I was just blowing off the issue entirely.)

  • The Old New Thing

    Rob Cockerham investigates those companies that pay cash for gold

    • 9 Comments

    Rob Cockerham seems to have a lot of spare time, which is great for the rest of us, because he investigates all those things we simply don't have the time for, and then posts the results on his Web site ("The sixth-best website in the world").

    Today's highlight is a pair of investigations he performed some time ago which seem to show two sides of one industry.

    That Web site is a sinkhole of time-wastage. If you're not careful, you'll find yourself clicking around from story to story, like the How much is inside? adventures, in which he investigates things like how many threads per inch are there in 360-thread count pillowcases? Or his gallery of costumes (for Hallowe'en or other events), including my favorite: Paparazzi.

Page 372 of 449 (4,481 items) «370371372373374»