August, 2012

  • The Old New Thing

    Of what possible legitimate use are functions like CreateRemoteThread, WriteProcessMemory, and VirtualProtectEx?

    • 26 Comments

    There are a bunch of functions that allow you to manipulate the address space of other processes, like Write­Process­Memory and Virtual­Alloc­Ex. Of what possible legitimate use could they be? Why would one process need to go digging around inside the address space of another process, unless it was up to no good?

    These functions exist for debuggers. For example, when you ask the debugger to inspect the memory of the process being debugged, it uses Read­Process­Memory to do it. Similarly, when you ask the debugger to update the value of a variable in your process, it uses Write­Process­Memory to do it. And when you ask the debugger to set a breakpoint, it uses the Virtual­Protect­Ex function to change your code pages from read-execute to read-write-execute so that it can patch an int 3 into your program.

    If you ask the debugger to break into a process, it can use the Create­Remote­Thread function to inject a thread into the process that immediately calls Debug­Break. (The Debug­Break­Process was subsequently added to make this simpler.)

    But for general-purpose programming, these functions don't really have much valid use. They tend to be used for nefarious purposes like DLL injection and cheating at video games.

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

  • The Old New Thing

    Microspeak: planful

    • 20 Comments

    Every year, Microsoft invites its employees to fill out a poll which asks questions regarding all sorts of things. One of the things Microsoft employees are asked to evaluate is whether they think that their vice president is acting planfully.

    The tricky part about that question is that nobody knows exactly what the word planfully means.

    Merriam-Webster defines planful as "full of plans : RESOURCEFUL, SCHEMING." Is that what they're asking us? Whether our vice president is resourceful and scheming? Is that a good thing or a bad thing?

    The OED, on the other hand, defines it as "Full or rich in plans; characterized by planning; organized, systematic." It's not clear whether this means that the person goes into a situation with a plan ahead of time, or that once they get into a situation, they develop a plan for getting out. (Maybe both?)

    I caught a vice president using the word planful during a meeting, so I raised my hand and asked, "What does planful mean?" (Most people don't have the nerve to raise their hand during a meeting and ask, "Um, what does that word mean?")

    The vice president replied, "Actually, I don't think it's a real word. I think [name of a senior manager] made it up."

    I followed up: "Well, in that case, why are we asked to evaluate you every year on whether your actions are planful? How can we answer a question that uses a made-up word nobody knows the definition of?"

    Obligatory xpclient example: "Was it a planful decision to introduce the auto-sorting problem?"

    Reminder: Microspeak is not merely terms unique to Microsoft, but also terms used at Microsoft more often than in general.

  • The Old New Thing

    Why is the desktop treated so special in window ordering?

    • 26 Comments

    Clipboarder Gadget wants to know why the desktop is treated so special in window ordering. Specifically, when you double-click a folder icon on the desktop, and the immediately close it, why does focus not go back to the desktop? Instead it goes to some random window.

    Actually, it's the other way around. Focus is going to a random window specifically because the desktop is not being treated special.

    The rules for focus transfer when a window is closed is that focus goes to the owner, if any. If there is no owner, then the window manager starts looking around, in a rather complicated way, but the next enabled window in the Z-order is on the candidate list. And since the desktop sits at the bottom of the Z-order, it almost never wins the "next enabled window in the Z-order" contest. Having the desktop somehow "jump the queue" and gain focus under certain conditions would mean giving the desktop special treatment.

    Even if you wanted to grant the desktop that special treatment, what would the rules be for deciding when to grant the desktop exception? The Explorer window for the folder you opened has no special connection to the desktop window in the window hierarchy. It belongs to a different thread. Depending on how your system is configured, it might even be in another process. What would you use to determine that closing that window should move focus to the desktop?

    Consider: You double-click the icon to open the folder. Then you click on Notepad. Then you click back on the folder window and close it. Shouldn't focus go to Notepad? Why should the desktop be special?

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

  • The Old New Thing

    Get your Contoso-branded merchandise while you can

    • 15 Comments

    Long-time observers are familiar with Contoso, the fake company name used in Microsoft samples and demonstrations. The Windows Phone folks have started running with the joke and creating their own line of Contoso-branded merchandise. (Of course, if you get the Contoso mug, you should fill it with Fourth Coffee.)

  • The Old New Thing

    FORFILES, for your fancier batch file enumeration needs

    • 20 Comments

    Crack open open the champagne: Batch File Week is finally over!

    Variations on the for /f %%i in ('dir /b ...') will let you repeat an operation on the contents of a directory, possibly even recursively if you add the /s option, with some basic attribute-level filtering if you add the /a or /a- flags.

    For your fancy recursive file operations, there's a tool called FORFILES which iterates through the contents of a directory (recursively if requested), executing a command on each item it finds. It also has additional filtering capability, like selecting files based on their last-modified time. For example, you could copy all files in the current directory which were modified today:

    forfiles /D +0 /c "cmd /c copy @file \\server\today"
    

    Unfortuantely, the /D option is not as flexible as one might like. For example, while it can pick files modified today, it can't pick files modified in the last week, because the relative-date-picker knows only how to pick files modified on or before a date in the past or files modified on or after a date in the future. (Who the heck wants to operate on files modified in the future? Except perhaps the Microsoft Research folks who are working on that time machine.)

    You can type FORFILES /? for more information on what you can do (and by seeing what's omitted, what you can't do).

    If the command you want to execute is rather long, you can offload it back into the batch file being executed:

    @echo off
    if "%1"=="/callback" goto callback
    forfiles /D +0 /c "cmd /c call "%~f0" /callback @isdir @file @fsize"
    goto :eof
    :callback
    rem %2 = @isdir
    rem %3 = @file
    rem %4 = @fsize
    if %2==TRUE echo Skipping directory %3.&goto :eof
    echo Copying file %3 to \\server\today (%4 bytes)
    

    One gotcha here is that since each command runs in a sub-shell, it can read environment variables, but any modifications it makes to environment variables will be lost since the command is modifying only its local environment variables. A workaround for this is to use FORFILES to select the data to operate on, but use FOR to actually perform the operation. Since FOR runs inside the main command interpreter, it can modify environment variables.

    set TOTALSIZE=0
    for /f %%i in ('forfiles /d +0 /c "cmd /c if @isdir==FALSE echo @fsize"') ^
    do set /a TOTALSIZE=TOTALSIZE + %%i
    

    Here, we use FORFILES to enumerate all the files (not directories) modified today and print their sizes. We wrap this inside a FOR which reads the sizes and adds them up.

    If the operation you want to perform on each file is complex, you can of course offload it into a subroutine call.

    for /f %%i ^
    in ('forfiles /d +0 /c "cmd /c if @isdir==FALSE echo @fsize"') ^
    do call :subroutine %%i
    

    I'm cheating here because I know that @fsize doesn't contain spaces. If you are processing file names, then you need to be more careful.

    for /f "tokens=*" %%i ^
    in ('forfiles /d +0 /c "cmd /c if @isdir==FALSE echo @fname"') ^
    do call :subroutine %%i
    
  • The Old New Thing

    If you're going to throw a badminton match, you have to be less obvious about it

    • 37 Comments

    It may be possible based on your location to view what NBC euphemistically calls "highlights" from the women's badminton doubles match between China's Yu Yang/Wang Xiaoli and South Korea's Jung Kyung Eun/Kim Ha Na. The serves go laughably into the net, there is barely any attempt to chase down shots, and returns go far out of bounds. If this is top-level badminton, I think I could be a world champion.

    Both sides had secured their advance into the next round, and Wired explained why both teams decided that a strategic loss would be advantageous. Julie VanDusky-Allen provides a game-theoretical analysis of the situation. (Even if you randomize the seeds in the knockout portion of the tournament, you can still get into a situation where a team in the round-robin portion of the tournament may decide that it is advantageous to lose a match on purpose.¹)

    Partway into the match, an official warns both teams that if they do not make an effort to win, the teams will both be disqualified. That served to improve the quality of play only marginally.

    Okay, they need to study soccer or American professional basketball, where intentionally losing is a long-standing tradition: You need to make it look like you're trying, or people are going to figure you out. For example, play normally most of the time, but then have a mental lapse and "accidentally" make an error that concedes a point.

    At least fake an injury. That'll let you start playing badly with plausibility.

    (Although these techniques for throwing a match subtly probably don't work if your opponent is also trying to lose.)

    Since the attempt to get both sides to play to win didn't seem to help, perhaps the officials should have announced, "We have decided to assist in motivating the two sides by declaring that the loser of the match will be disqualified from the tournament."

    Now they have something to play for.

    ¹ Consider a four-team group with teams A, B, C, and D. In round 1, A defeats B 5–1 and C defeats D 2–1. In round 2, A defeats D 5–1 and B defeats C 2–1. At this point, A is guaranteed advancement as long as it doesn't lose to C by more than 8 points. If A defeats C, then B will advance. But A may decide that it prefers to play against C in the knockout portion of the tournament. In that case, it can intentionally lose to C in the third round by 4 points (leaving a comfortable margin of error), and as long as B doesn't win by more than 7 points, A will get its wish: C will advance.

  • The Old New Thing

    Exiting a batch file without exiting the command shell -and- batch file subroutines

    • 17 Comments

    Prepare your party hats: Batch File Week is almost over.

    In your batch file, you may want to exit batch file processing (say, you encountered an error and want to give up), but if you use the exit command, that will exit the entire command processor. Which is probably not what you intended.

    Batch file processing ends when execution reaches the end of the batch file. The trick therefore is to use the goto command to jump to a label right before the end of the file, so that execution "falls off the end".

    @echo off
    if "%1"=="" echo You must provide a file name.&goto end
    if NOT EXIST "\\server\backup\%USERNAME%\nul" mkdir "\\server\backup\%USERNAME%"
    if NOT EXIST "\\server\backup\%USERNAME%\nul" echo Unable to create output directory.&goto end
    copy "%1" "\\server\backup\%USERNAME%"
    :end
    

    Here, there are two places where we abandon batch file execution. One is on an invalid parameter, and another is if the output directory couldn't be created (or if it isn't a directory at all).

    The batch command interpreter provides a courtesy label to simply this technique: The special goto target goto :eof (with the colon) jumps to the end of the batch file. It's as if every batch file had a hidden goto label called :eof on the very last line.

    The goto :eof trick becomes even more handy when you start playing with batch file subroutines. Okay, let's back up: Batch file subroutines?

    By using the call command, a batch file can invoke another batch file and regain control after that other batch file returns. (If you forget the call, then control does not return. In other words, the default mode for batch file invocation is chain.) In other words, the call command lets you invoke another batch file as a subroutine. The command line parameters are received by the other batch file as the usual numbered parameters %1, %2, etc.

    It's annoying having to put every subroutine inside its own batch file, so the command interpreter folks added a way to call a subroutine inside the same batch file. The syntax for this is call :label parameter parameter parameter. This is logically equivalent to a batch file recursively calling itself, except that execution begins at the specified label instead of the first line of the file. (It's as if a secret goto label were added to the top of the file.)

    And since it is a batch file, execution of the called subroutine ends when execution falls off the end of the file. And that's where the special goto target comes in handy. At the end of your subroutine, you can jump to the end of the batch file (so that execution falls off the end) by doing a goto :eof.

    In other words, goto :eof is the return statement for batch file subroutines.

    Let's take it for a spin:

    @echo off
    call :subroutine a b c
    call :subroutine d e f
    goto :eof
    
    :subroutine
    echo My parameters are 1=%1, 2=%2, 3=%3
    goto :eof
    

    That final goto :eof is redundant, but it's probably a good habit to get into, like putting a break; at the end of your last case.

    The subroutine technique is handy even if you don't really care about the subroutine, because stashing the arguments into the %n parameters lets you use the tilde operators to process the inbound parameter.

    @echo off
    call :printfilesize "C:\Program Files\Windows NT\Accessories\wordpad.exe"
    goto :eof
    :printfilesize
    echo The size of %1 is %~z1
    goto :eof
    

    Okay, this isn't actually much of a handy trick because you can also do it without a subroutine:

    @echo off
    for %%i ^
    in ("C:\Program Files\Windows NT\Accessories\wordpad.exe") ^
    do echo The size of %%i is %%~zi
    

    On the other hand, the subroutine trick combines well with the FOR command, since it lets you put complex content in the loop body without having to mess with delayed expansion:

    @echo off
    setlocal
    set DISKSIZE=1474560
    set CLUSTER=512
    set DISKS=1
    set TOTAL=0
    for %%i in (*) do call :onefile "%%i"
    set /a DISKS=DISKS+1
    echo Total disks required: %DISKS%
    endlocal
    goto :eof
    
    :onefile
    set /a SIZE=((%~z1 + CLUSTER - 1) / CLUSTER) * CLUSTER
    
    if %SIZE% GEQ %DISKSIZE% (
        echo File %1 does not fit on a floppy - skipped
        goto :eof
    )
    
    set /a TOTAL=TOTAL+SIZE
    if %TOTAL% GEQ %DISKSIZE% (
        echo ---- need another disk
        set /a DISKS=DISKS+1
        set /a TOTAL=SIZE
    )
    echo copy %1
    goto :eof
    

    This program calculates the number of floppy disks it would take to copy the contents of the current directory without compression.

    The setlocal command takes a snapshot of the environment for restoration when we perform the endlocal at the end. That will clean up our temporary variables when we're done.

    The first two variables are parameters for the calculation, namely the disk capacity and the cluster size. (We're assuming that the root directory can hold all the files we may ultimately copy. Hey, this is just a demonstration, not a real program.)

    The next two variables are our running total of the number of disks we've used so far, and how many bytes we've used on the last disk.

    The for command iterates over all the files in the current directory. For each one, we call :onefile with the file name.

    The :onefile subroutine does all the real work. First, it takes the file size %~z1 and rounds it up to the nearest cluster. It then sees if that size is larger than a floppy disk; if so, then we're doomed, so we just skip the file. Otherwise, we add the file to the current disk and see if it fits. If not, then we declare the disk full and put the file on a brand new disk.

    After the loop is complete, we print the number of floppy disks we calculated.

    (This algorithm erroneously reports that no files require one disk. Fixing that is left as an exercise.)

    There's your quick introduction to the secret :eof label and batch file subroutines.

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

  • The Old New Thing

    You gotta fight for your right to parry

    • 17 Comments

    (The headline was stolen from one of my cleverer friends.)

    I'm taking time out of my busy vacation to draw your attention (if it hasn't been already) to the story of South Korean fencer Shin A Lam, who got screwed out of her trip to the finals of the women's individual epeé.¹ The story is heart-wrenching, and the photojournalism is moving in its simplicity. (Assisted in large part by the rule that fencers must not leave the piste while the appeal is in progress.)

    The FIE, fencing's international governing body, later chose to award Shin a special medal "For aspiration to win and respect of the rules." Apparently, the FIE's timekeeping equipment was not up to the task because "They never expected this kind of thing to happen in the last second, three attacks. Their timekeeping machine is only in seconds, not points of a second."

    Um, right. Because nobody expected fencing to have sudden bursts of intense, frantic activity which require split-second accuracy.

    ¹ To avoid matches which last indefinitely, fencing has a concept known as priority: Before the final overtime round, one of the fencers is chosen at random to have priority. If no winner is determined by the final round, then the fencer with priority is declared the winner. Shin had priority, so if the ruling had been no-touch, she would have been the one to advance.

  • The Old New Thing

    How do I find the most recently created file in a directory from a batch file?

    • 29 Comments

    We've reached Hump Day of Batch File Week. Remember, nobody actually likes batch programming. You merely tolerate it.

    Today, we'll find the most recently-created item in a directory. (For example, we have a server that holds our daily builds, and you might want to write a batch file that automatically installs the latest build.)

    There may be better ways, but what I do is ask for a list sorted oldest-to-newest, and then choose the last one.

    for /f %%i in ('dir /b/a-d/od/t:c') do set LAST=%%i
    echo The most recently created file is %LAST%
    

    This trick works by asking the dir command to list just the names (/b) of just the files /a-d, sorted by date (/od), based on the creation time (/t:c).

    Each time a new file is reported, its name is stored in the LAST variable, overwriting the previous one. When the loop finishes, the LAST variable contains the name of the newest file, since that's the one that didn't get overwritten.

    You can tweak the command line to perform other queries. For example, if you want the newest file, then just ask for a reverse sort (/o-d). If you want the file sorted by modified time rather than creation time, then use /t:w. You get the idea.

    Limitations: The implementation above assumes that no files contain spaces in their name. Removing this limitation is left as an exercise.

Page 3 of 3 (29 items) 123