• The Old New Thing

    Magic dirt, the fate of former professional athletes, and other sports randomness


    A sports-related (mostly baseball) link dump.

  • The Old New Thing

    What do SizeOfStackReserve and SizeOfStackCommit mean for a DLL?



    Those fields in the IMAGE_OPTIONAL_HEADER structure are meaningful only when they appear in the EXE. The values provided in DLLs are ignored.

    Size­Of­Heap­Reserve and Size­Of­Heap­Commit fall into the same category. In general, flags and fields which control process settings have no effect when declared in a DLL. We've seen a few examples already, like the /LARGE­ADDRESS­AWARE flag or the markers which indicate the default layout direction.

  • The Old New Thing

    Why doesn't the Open Files list in the Shared Folders snap-in show all my open files?


    A customer wanted a way to determine which users were using specific files on their server. They fired up the Shared Folders MMC snap-in and went to the Open Files list. They found that the results were inconsistent. Some file types like .exe and .pdf did show up in the list when they were open, but other file types like .txt did not. The customer asked for an explanation of the inconsistency and for a list of which file types work and which ones don't.

    The customer is confusing two senses of the term open file. From the file system point of view, an open file is one that has an outstanding handle reference. This is different from the user interface concept of "There is an open window on my screen showing the contents of the file."

    The Open Files list shows files which are open in the file system sense, not in the user interface sense.

    Whether a file shows up in the Open Files list depends on the application that is used to open the file (in the user interface sense). Text files are typically opened by Notepad, and Notepad reads the entire contents of the file into memory and closes the file handle. Therefore, the file is open (in the file system sense) only when it is in the process of being loaded or saved.

    There is no comprehensive list of which types of files fall into which category because the behavior is not a function of the file type but rather a function of the application being used to view the file. (If you open a .txt file in Word, I believe it will keep the file system handle open until you close the document window.)

    The customer seemed satisfied with the explanation. They ran some experiments and observed that Hey, check it out, if I load a really big text file into Notepad, I can see it show up in the Open Files list momentarily. They never did come back with any follow-up questions, so I don't know how they went about solving the original problem. (Maybe they used a SACL to audit who was opening the files.)

  • The Old New Thing

    You don't make something easier to find by hiding it even more deeply


    Commenter rolfhub suggested that, to help people recover from accidentally going into Tiny Footprint Mode, the Task Manager could display a right-click context menu with an entry to return to normal mode.

    My initial reaction to this was Huh? Who right-clicks on nothing? Tiny Footprint Mode is itself already a bad secret hidden setting. Having the exit from the mode be a right-click menu on a blank space is a double-secret hidden setting.

    If I had dictatorial control over all aspects of the shell, I would put a Restore button  in the upper right corner to let people return to normal mode.

  • The Old New Thing

    Why are the alignment requirements for SLIST_ENTRY so different on 64-bit Windows?


    The Interlocked­Push­Entry­SList function stipulates that all list items must be aligned on a MEMORY_ALLOCATION_ALIGNMENT boundary. For 32-bit Windows, MEMORY_ALLOCATION_ALIGNMENT is 8, but the SLIST_ENTRY structure itself does not have a DECLSPEC_ALIGN(8) attribute. Even more confusingly, the documentation for SLIST_ENTRY says that the 64-bit structure needs to be 16-byte aligned but says nothing about the 32-bit structure. So what are the memory alignment requirements for a 32-bit SLIST_ENTRY, 8 or 4?

    It's 8. No, 4. No wait, it's both.

    Officially, the alignment requirement is 8. Earlier versions of the header file did not stipulate 8-byte alignment, and changing the declaration would have resulted in existing structures which (inadvertently) misaligned the field changing size and layout when the new requirement was imposed. So the 32-bit structure was sort-of grandfathered in. You should still align it on 8-byte boundaries, but the header file doesn't enforce it to avoid breaking existing code.

    Fortunately, when the 64-bit version was introduced, the proper alignment directive was introduced right off the bat. How about that: sometimes Microsoft learns from its mistakes after all.

    Why are the alignment requirements greater than the natural word size? To avoid the ABA problem. A standard workaround for the ABA problem is to append additional information (a "tag") to the pointer so that when the value changes from B back to A, the tag ensures that the second A still looks different from the first one. Many CPU architectures have a "double-pointer-sized atomic compare-and-swap" instruction, and some of them have the additional requirement that the double-pointer needs to be on a double-pointer boundary (8 bytes for 32-bit pointers and 16 bytes for 64-bit pointers).

    "But wait, the double-pointer compare-and-swap is used on the SLIST_HEADER, not on the SLIST_ENTRY. Why does the SLIST_ENTRY need to be double-pointer aligned, too?"

    While it's true that many CPU architectures have a "double-pointer-sized atomic compare-and-swap" instruction, some support only a "pointer-sized atomic compare-and-swap". For example, the original AMD64 architecture did not have a CMPXCHG16B instruction; the largest data size for an atomic compare-and-swap was 8 bytes. As a result, the Slist functions need to pack a 64-bit pointer, a list depth, and tag information into a single 64-bit value. One of the tricks they used was imposing a memory alignment of 16 bytes. This freed up four bits in the pointer for use as a tag.

  • The Old New Thing

    Ow, I'm too safe!


    One of my friends is a geek, and, naturally, fully researches everything he does, from cement pouring to bicycle parts, perhaps a bit obsessively. He made sure to get five-point restraints for his children's car seats, for example. And he naturally tightens the belts snugly when putting his children in the car.

    At one point, as he was strapping his daughter in, she complained, "Ow! I'm too safe!"

    Because as far as she was concerned, "being safe" was a synonym for "having a tight seat belt." I leave you to figure out how she came to this conclusion.

  • The Old New Thing

    Why does IFileOperation skip junctions even though I passed FOFX_NOSKIPJUNCTIONS?


    The IFile­Operation::Set­Operation­Flags method accepts a number of flags to modify the file operation, among them today's subject FOFX_NO­SKIP­JUNCTIONS. A customer reported that they couldn't get this flag to work: Whether they set it or not, the IFile­Operation skipped over file system junctions.

    The term junction evolved two independent different meanings. The shell team invented the term shell namespace junction in Windows 95 to refer to a point in the shell namespace in which one type of namespace extension is grafted into another. For example, a directory of the form name.{guid} serves as the transition point between the default file system namespace and a custom namespace.

    Meanwhile, the file system team developed the term NTFS junction point to refer to a directory entry which links to another location.

    If you just hear the word junction by itself, you need to use context to determine whether it is short for shell namespace junction or NTFS junction point.

    Since IFile­Operation::Set­Operation­Flags is a shell interface, the shell interpretation is more likely (and is the correct one in this case). The FOFX_NO­SKIP­JUNCTIONS flag has no effect on the behavior of the IFile­Operation interface on NTFS junction points; it modifies the behavior on shell namespace junctions.

  • The Old New Thing

    Starting up inside the box


    the shell team received two customer questions about a month apart which seemed unrelated but had the same root cause.

    I found that in Windows Vista, the xcopy command is ten times slower than it was in Windows XP. What is the source of this slowdown, and how can I fix it?
    We have an application which takes a very long time to start up on Windows Vista than it did in Windows XP. We noticed that the slowdown occurs only if we set the application to autostart.

    Let's look at the second one first, since that customer provided a useful piece of information: The slowdown occurs only if they set the program to run automatically at logon. In Windows Vista, programs which are set to run automatically at logon run with reduced priority. This was done in response to the fact that application developers went angling for a bonus and decided to slow down the operating system overall in order to get their program to start up faster. To counteract this tragedy of the commons, the performance team runs these programs inside a job object with reduced CPU, I/O, and paging priority—which the performance team informally calls boxing— for 60 seconds, so that the user isn't forced to sit and wait for all these startup programs to finish doing whatever "really important" stuff they want to do.

    Okay, back to the first customer, the one who reported that xcopy was taking a long time. It took a bit of back-and-forth, but eventually the customer revealed that they were performing the xcopy in a batch file which they placed in the Startup group. Once they volunteered that information, the reason for the slowdown became obvious: Their batch file was running inside the box, and consequently ran with low-priority I/O.

    There is no way to escape the box, but it so happens that logon-triggered scheduled tasks are not placed inside a box. That's your escape hatch. Don't abuse it. (Of course, now that I've told everybody how to avoid being put in a box, everybody will now take advantage of it, because eventually, nothing is special any more.)

    Oh, and if you look more closely at the Delay_Sec setting on a Windows 7 machine, you'll see that it's set to zero, so the boxing behavior is effectively disabled on Windows 7. I guess the performance team gave up. "Fine, if you want your computer to run like a dog when it starts up, then go right ahead. I won't try to save you from yourself any more."

    Bonus chatter: You can explicitly "put yourself inside a box" by using the PROCESS_MODE_BACKGROUND_BEGIN process priority mode. Programs which are intended to run in the background with minimal impact on the rest of the system can use this mode.

  • The Old New Thing

    Why does creating a shortcut to a file change its last-modified time... sometimes?


    A customer observed that sometimes, the last-modified timestamp on a file would change even though nobody modified the file, or at least consciously took any steps to modify the file. In particular, they found that simply double-clicking the file in Explorer was enough to trigger the file modification.

    It took a while to puzzle out, but here's what's going on:

    When you double-click a file in Explorer, Explorer adds it to the Recent Items list. Internally, this is done by creating a shortcut to the item. The nice thing about a shortcut is that it knows how to track its target. That way, if you move an item, then try to open it from the Recent Items list, the shortcut tracking code will try to find where you moved it to. You moved the file. The shortcut still works. Magic.

    Shortcut target tracking magic is accomplished with the assistance of object identifiers, and object identifiers, as we saw earlier, are created on demand the moment somebody first asks for one.

    And that's where the file modification is coming from. If the file is freshly-created, it won't have an object identifier. When you create a shortcut to it (which happens implicitly when it is added to the Recent Items list), that triggers the creation of an object identifier, which in turn updates the last-modified time on the file.

    Frustratingly, the Link­Resolve­Ignore­Link­Info and No­Resolve­Track policies do not prevent the creation of object identifiers. Those policies control whether the tracking information is used during the resolve process, but they don't control whether the tracking information is obtained during shortcut creation. (Who knows, maybe you're creating the shortcut to be used on a machine where those policies are not in effect.) To suppress collecting the volume information and object identifier at shortcut creation time, you need to pass the SLDF_FORCE_NO_LINKINFO and SLDF_FORCE_NO_LINKTRACK flags to the IShell­Link­Data­List::Set­Flags method when you create the shortcut.

  • The Old New Thing

    Why does the runas command require its command line to be quoted?


    Commenter teo complained that the runas command requires its command line to be quoted.

    Well, if you think about it, why single out runas? Pretty much all programs require their command line to be quoted if they contain special characters (like spaces that you want to be interpreted as part of a file name instead of as an argument separator). The runas command is just doing things the way everybody else does.

    Recall that on Windows, programs perform their own command line parsing. This isn't unix where the command shell does the work of parsing quotation marks and globs before handing the (now-partly-parsed) command line to the child process. Mind you, most programs do not do their own custom parsing; they rely on the C runtime library to do the parsing into arguments.

    Okay, but let's single out the runas command anyway, because runas does live in a slightly different world. It is a convention dating back to MS-DOS that programs which accept a command line as an argument do so without requiring quoting. The archetypal example of this is the command processor itself. Whatever you pass after the /C flag is treated as the command line to execute. Once the /C is encountered, parsing stops and everything from there to the end of the raw command line is treated as the argument. (It also imposes the requirement that /C be the last parameter on the command line.) (Note also that there is a special weirdo rule in the cmd.exe parser with respect to the /C and /K switches; see cmd /? for details.)

    (Therefore, if you want a program that forwards its command line to another program, the way to do this is not to parse your command line and then try to unparse it but rather to just forward the original command line.)

    The authors of the runas program appeared not to be aware of this historical convention at the time they wrote it. They just used the regular C runtime library command line parser, unaware that "programs which accept a command line on the command line" fall into a special alternate reality. Hence the need for the double-extra-quoting.

    Back when the runas program was being developed, I pointed out this historical alternate reality to the people responsible for the runas program. They took my remarks under advisement but evidently chose to stick with the "standard" parsing rules rather than entering the little-known alternate reality. (As a consolation prize, they did add some examples at the end of the runas /? output to explain how quotation marks should be used.)

Page 126 of 458 (4,572 items) «124125126127128»