Win32

Use FILE_SHARE_DELETE in your shell extension

Michael Geary | Wed, 2004-09-29 18:24
category

A Windows shell extension that provides information from the contents of a file has to open the file to do it. Opening a file locks it to some extent or another, depending on the file sharing flags you use. Even if you open the file for only a moment, that can be long enough to interfere with another program's use of the file.

What happens when someone drags a file from one folder to another, and you have a shell extension that renders thumbnails for the selected file type? Windows calls your IExtractImage interface and you start rendering the thumbnail. Then as soon as your customer releases the mouse, Windows tries to move the file to the new folder. If they move fast enough, this can happen while you've still got the file open to render the thumbnail. That results in this lovely message:

Error Moving File

If they're lucky, they'll try again and go a little slower, and it will work! You've finished rendering the thumbnail, closed the file, and Windows can move it with no problem.

There's an easy way to fix this for Windows NT, 2000, and XP. In the CreateFile() call that opens the file, use FILE_SHARE_READ | FILE_SHARE_DELETE in the dwShareMode parameter.

The MSDN documentation doesn't make it clear at all, but FILE_SHARE_DELETE works with MoveFile() in the same way it does with DeleteFile(). In other words, it gives you Unix-style delete/rename semantics. Even while you have the file open, Windows can delete it or rename it right out from under you, but you can keep reading it—your handle to the file remains valid until you close it.

So, in the case above, Windows moves the file to the destination folder without interference from your thumbnail code.

Mike Mascari ran a test of this and posted the results in the comp.databases.postgresql.hackers newsgroup:

Well, here's the test:

foo.txt contains "This is FOO!"
bar.txt contains "This is BAR!"

Process 1 opens foo.txt
Process 2 opens foo.txt
Process 1 sleeps 7.5 seconds
Process 2 sleeps 15 seconds
Process 1 uses MoveFile() to rename "foo.txt" to "foo2.txt"
Process 1 uses MoveFile() to rename "bar.txt" to "foo.txt"
Process 1 uses DeleteFile() to remove "foo2.txt"
Process 2 awakens and displays "This is FOO!"

On the filesystem, we then have:

foo.txt containing "This is BAR!"

The good news is that this works fine under NT 4 using just MoveFile(). The bad news is that it requires the files be opened using CreateFile() with the FILE_SHARE_DELETE flag set. The C library which ships with Visual C++ 6 ultimately calls CreateFile() via fopen() but with no opportunity through the standard C library routines to use the FILE_SHARE_DELETE flag. And the FILE_SHARE_DELETE flag cannot be used under Windows 95/98 (Bad Parameter). Which means, on those platforms, there still doesn't appear to be a solution. Under NT/XP/2K, AllocateFile() will have to modified to call CreateFile() instead of fopen(). I'm not sure about ME, but I suspect it behaves similarly to 95/98.

Even two years after Mike's post, the C runtime hasn't got much better. The _fsopen() and _sopen() functions claim to support file sharing, but neither one supports FILE_SHARE_DELETE. For a shell extension, that may not matter; you may just use the Win32 file I/O functions directly. If you want the buffering that the stream I/O functions provide, you can use CreateFile() to open the file with FILE_SHARE_DELETE, then _open_osfhandle() to get a C runtime file descriptor, and _fdopen() to open a stream from that.

Sorry, FILE_SHARE_DELETE doesn't work on 95, 98, or Me; you have to leave the flag off. I'm not sure how you fix this problem for those OSes.

Energizer Project: Keeps Building and Building

Michael Geary | Thu, 2004-08-12 15:37

Did you ever have a Visual C++ project that won’t stop building? It builds OK, but if you start the debugger or do another Ctrl+Shift+B, it says it’s out of date and wants to build again? Every time?

This happened to me and I was stumped. There was nothing in the Output window to tell me what was wrong. It looked like a perfectly successful build:

------ Build started: Project: Test,
Configuration: Debug Win32 ------

Compiling resources...
Linking...

Build log was saved at
"file://c:\Test\Debug\BuildLog.htm"
Test - 0 error(s), 0 warning(s)

-------------- Done --------------

    Build: 1 succeeded, 0 failed, 0 skipped

The only problem was it compiled those resources every time. It never thought they were up to date.

I tried some Google searches. Nothing. This was annoying me, and the rest of my team.

Finally, out of sheer frustration, I Ctrl+clicked on that “Build log” link, like the helpful tooltip suggested.

Oh. Now it tells me:

Compiling resources...
Linking...

Test : warning PRJ0041 : Cannot find missing
dependency 'ICON_FILE' for file 'Test.rc'.
Your project may still build, but may
continue to appear out of date until this
file is found.

That gives me a desperately needed clue. Looking at Test.rc, I see that I’d coded:

#ifdef DEMO
    #define ICON_FILE "Icons\Demo.ico"
#else
    #define ICON_FILE "Icons\Full.ico"
#endif

1 ICON DISCARDABLE ICON_FILE

Well, it sounded like a good idea at the time, honest.

The resource compiler has no problem with this, but apparently the dependency checker can’t handle it.

Changing it to this fixed it:

#ifdef DEMO
    1 ICON DISCARDABLE "Icons\Demo.ico"
#else
    1 ICON DISCARDABLE "Icons\Full.ico"
#endif

The Moral:

  • The information you need may be hiding behind a link. Just because the Output window has always told you about build problems doesn’t mean it will tell you today.
  • If your product has an Output window that almost always provides complete information, fix it so it always does.

NULL hInstance Considered Harmful

Michael Geary | Wed, 2004-08-11 16:10
category

On a couple of occasions, I've converted large Windows applications from EXEs to DLLs which are loaded by stub EXEs. There are several reasons you might want to do this, and for the most part it's surprisingly easy. Most Windows code doesn't know or care if it's running in a DLL or EXE, as long as it has the right instance handle for any functions that load resources or the like.

There were a few Windows functions that gave us grief, though. These are the functions that accept a NULL hInstance to mean the current process. I used to think this was a nice convenience, but all the code that used a NULL hInstance had to be converted to take an explicit hInstance.

I searched for the functions that came to mind and fixed them:

GetModuleBaseName
GetModuleFileName
GetModuleHandle

But I forgot about an entire group of functions and had to find them the hard way, through some tedious debugging:

EnumResourceLanguages
EnumResourceNames
EnumResourceTypes
FindResource
FindResourceEx
FindResourceWrapW
LoadResource

Are there more functions like this?

Ruby iterators and C callback functions

Michael Geary | Mon, 2004-08-09 00:00

Mike Sax wonders what’s the fuss about iterators. Aren’t they just a fancy use of function pointers? Indeed, Mike has hit the nail on the head. Consider the window iterator that’s been built into Windows since 1.0:

BOOL EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam );

This function iterates through all of the top-level windows (children of the desktop window) and calls lpEnumFunc for each one, passing it the HWND of each window and the lParam that you passed to EnumWindows.

So lParam is how you get to provide some state that the enumeration function can make use of. Suppose you wanted to write a function that counted the number of visible top-level windows. Your C code might look like this:

struct MyEnumWindowState
{
    int nVisible;
};

BOOL CALLBACK MyEnumWindowsProc( HWND hwnd, LPARAM lParam )
{
    MyEnumWindowState* pState = (MyEnumWindowState*)lParam;
    if( IsWindowVisible(hwnd) )
        pState->nVisible++;
}

int CountVisibleWindows()
{
    MyEnumWindowState state;
    state.nVisible = 0;

    EnumWindows( MyEnumWindowsProc, (LPARAM)&state );
    return state.nVisible;
}

This works, but it is rather tedious. So Windows 2.0 added the GetWindow function, which lets you simply ask for a window’s child or next sibling. That simplifies the overall structure of the code, especially if you use the GetFirstChild and GetNextSibling macros defined in windowsx.h:

int CountVisibleWindows()
{
    int nVisible = 0;
    HWND hwnd = GetDesktopWindow();

    for( hwnd = GetFirstChild(hwnd);
         hwnd;
         hwnd = GetNextSibling(hwnd) )
    {
        if( IsWindowVisible(hwnd) )
            nVisible++;
    }

    return nVisible;
}

That’s it, just one function, no callback function or struct definition needed. We don’t need the struct because the code inside the loop can directly reference the nVisible variable defined in the function.

But the simplification came at a price: We had to write the loop ourselves, asking explicitly for the first child of the desktop window and then the next sibling of each child window.

Also, it doesn’t work.

What if another application creates or destroys a top-level window, or just changes a window’s Z-order, while you’re in the loop? You’ll either miss a window, count one twice, or crash with an invalid window handle.

To handle these cases, you need a bit more complexity. If you had a way to temporarily lock all window creation and destruction, you could quickly create a list of all the windows and then release the lock, then enumerate from that list, perhaps also doing a last-minute check when you enumerate each window to skip any that get destroyed during enumeration. Or, you might set a Windows hook to notify you of any windows created, destroyed, or moved in the Z-order, so you could deal with them appropriately.

Whatever you did, it would be enough code that you wouldn’t want to duplicate it each time you wanted to write a window loop. The GetFirstChild/GetNextSibling style of loop doesn’t really facilitate that kind of code isolation. The EnumWindows style enumerator completely separates the code that does the iterating (EnumWindows itself) from the code that receives the iteration (your callback function). But, it makes it harder to share state between the callback function and the code that called EnumWindows.

If you had a way to use a callback function, but have it more easily share state with the calling function, you’d have a winner. In C# and JavaScript, you can do this by using an anonymous callback function nested inside the surrounding code. Because of lexical scoping, the callback function can access variables in the parent function as easily as it can access its own.

Both those language have enough extra syntactic cruft that when you look at a simple example using nested anonymous functions, it’s easy to be unimpressed. The payoff shows up in more complicated, real-life coding situations.

Code blocks in Ruby simplify this technique down to its essence, making it useful even for simple cases. Assuming a good Rubyesque Windows interface library, our function might be something like:

def countVisibleWindows()
    nVisible = 0

    Win.enumWindows do |window|
        nVisible += 1 if window.visible?
    end

    nVisible
end

In this code, the enumWindows function takes a code block argument and calls that code block for each window, passing it the window as an argument. Because the code block is nested inside the countVisibleWindows function, it can access the nVisible variable directly.

This solves both our problems: The logic for iterating through the windows is separated out into the enumWindows function, and the callback function (code block) can access state variables cleanly and easily.

(In Ruby, a code block is a like a callback function, but it’s not quite a full-fledged function. A code block does not introduce a new scope for variables—it shares the scope of the enclosing function.)

Unfortunately, Ruby does not seem to have a Windows interface library that works like this. Ruby’s standard Win32 module provides a general way to call Windows DLL functions, but it doesn’t have a clean implementation of enumWindows that uses a code block.

However, MoonWolf has written a Ruby port of Perl’s Win32::GuiTest module that includes this kind of enumWindows function. It’s implemented in two parts: a low level function written in C that enumerates HWND values, and a higher level function written in Ruby that constructs Ruby window objects and enumerates them. The window object in Win32::GuiTest is a fairly thin wrapper that encapsulates an HWND and other window information.

The high-level enumWindows looks like this:

def enumWindows
    ret = []

    GuiTest::_enumWindows { |hwnd|
        win = createWindow( hwnd )
        ret << win
        yield win if block_given?
    }

    ret
end

This code calls the low-level _enumWindows function, which passes an HWND to the code block enclosed in curly braces. This code block creates the window object, appends to the ret array, and also yields the window object to a code block that was provided by the caller of enumWindows.

If I were implementing this, I think I would change it a bit. Typically a function like this either yields results to a code block, or it returns a value, but not both. And I would change the confusingly named createWindow function (which has no relation to the CreateWindow function in Windows):

def enumWindows
    if block_given?
        GuiTest::_enumWindows do |hwnd|
            yield newWindow( hwnd )
        end
    else
        result = []
        GuiTest::_enumWindows do |hwnd|
            result << newWindow( hwnd )
        end
        result
    end
end

Either way, our countVisibleWindows example ends up pretty much as I’d imagined:

def countVisibleWindows()
    nVisible = 0

    Win32::GuiTest.enumWindows do |window|
        nVisible += 1 if window.isWindowVisible
    end

    nVisible
end

The low-level enumWindows function that enumerates HWND values is implemented in C. The initialization code to add the enumWindows function is simply:

rb_define_module_function( mGuiTest, "_enumWindows", guitest_enumWindows, 0 );

where mGuiTest is a reference to the Win32::GuiTest module.

The guitest_enumWindows function is:

static VALUE guitest_enumWindows( VALUE self )
{
    EnumWindows( &EnumWindowsProc, 0 );
    return Qnil;
}

and the EnumWindowsProc callback is:

BOOL CALLBACK EnumWindowsProc( HWND hwnd, LPARAM lParam )
{
    rb_yield( INT2NUM((DWORD)hwnd) );
    return TRUE;
}

This shows how easy it is to extend Ruby with C code, adding functions that work just like ones written in Ruby.

So, how do all the calls and callbacks stack up when we run the countVisibleWindows function? Something like this:

countVisibleWindows
  enumWindows
    _enumWindows
      EnumWindows
        EnumWindowsProc
          rb_yield
            (code block in enumWindows)
              yield
                (code block in
                 countVisibleWindows)

In everyday use, of course, you don’t worry about that whole call stack, just the part of it you’re working with.

Use elementsof(sz), not sizeof(sz)

Michael Geary | Fri, 2004-08-06 18:36

I had to fix a bug recently where my shell extension was crashing another application when you used that app’s File Open dialog.

This application has a thumbnail view of the selected file in the File Open dialog, which they generate the same way as Windows Explorer: by loading a shell extension for the selected filetype and calling its IExtractImage interface. It’s a fairly weird protocol: First they call your IPersistFile::Load to give you the filename, then you give them back the same filename when they call IExtractImage::GetLocation. Finally they call IExtractImage::Extract and that’s when you generate the thumbnail.

But, after my GetLocation method returned, the application silently exited. What could be wrong? My code worked fine in Explorer.

GetLocation is a typical function that takes a character string buffer and length along with some other parameters (omitted here):

HRESULT GetLocation(
    LPWSTR pszPathBuffer,
    DWORD cchMax, etc. );

I noticed that this other app was giving me an unusually large file pathname buffer, 520 characters or 1040 bytes to be exact. This number sounded strangely familiar (and not just because of this).

Then I realized what happened. I’ve never seen the source code for this app I was crashing, but I just know it looked like this:

WCHAR szPath[MAX_PATH];
pExtractImage->GetLocation(
    szPath, sizeof(szPath), etc. );

Oops. The cchMax argument to GetLocation is a length in characters, but sizeof gives you the size in bytes. And we’re talking WCHAR here, so each character is two bytes. MAX_PATH is 260, making szPath 520 bytes long, the number that they passed into my code.

One way to fix the problem is:

WCHAR szPath[MAX_PATH];
pExtractImage->GetLocation(
    szPath, MAX_PATH, etc. );

That gives correct code, but I never like seeing MAX_PATH repeated like this. sizeof is in the right spirit, actually measuring the array length instead of repeating a constant, but it measures the wrong thing, bytes instead of characters (array elements).

I like to code this with the elementsof macro, defined as:

#define elementsof( array ) 
    ( sizeof(array) / sizeof((array)[0]) )

Then you can just use elementsof instead of sizeof:

WCHAR szPath[MAX_PATH];
pExtractImage->GetLocation(
    szPath, elementsof(szPath), etc. );

elementsof is handy anytime you need the length of a character string array or any array.

Of course, I didn’t have the luxury of fixing this code at its source (other than reporting the bug to the program’s authors). So I worked around it by checking for the bogus 520 character cchMax and cutting it back to 260 (MAX_PATH) characters.