Monday, August 31, 2009

PathMatchSpec Problems

Today I was debugging a problem in my application where a wildcard name failed to match. I traced the problem to significant issues with the implementation of PathMatchSpec() in the Windows API.

In short, do not expect this function to work like the command interpreter Cmd.exe. This function does not handle many boundary conditions, nor does it properly handle empty extensions.

The simplest example is this command, which correctly finds the Windows directory on all versions of Windows and MS-DOS 6.x:

dir c:\windows.*

However, this API call returns false on Vista:

BOOL b = ::PathMatchSpec("C:\\Windows", "C:\\Windows.*");

Other inconsistencies are shown in the table below. The "right" answer to these scenarios is unclear because MS-DOS did not support long filenames or spaces in filenames. Although various versions of Windows are themselves inconsistent, PathMatchSpec() does not agree with any of them. I would argue that the correct behavior is what Windows Vista does.

Command::PathMatchSpec("C:\\Windows", xxx);MS-DOSWin 9xWin NT
dir c:\windows.*FalseDisplays directory nameDisplays directory nameDisplays directory name
dir c:\windows.FalseDisplays directory contentsDisplays directory contentsDisplays directory contents
dir c:\windows...FalseDisplays directory nameDisplays directory contentsFail
dir "c:\windows "

(Note the trailing space)
Falsen/aDisplays directory contentsFail
dir "c:\windows ."

(Note the trailing space followed by a period.)
Falsen/aDisplays directory contentsFail

And yes, I did actually install MS-DOS to create this chart :-)

Thursday, August 27, 2009

Setting the default Windows SDK

Every time I install a new Windows SDK (or worse, a new copy of Visual Studio), I've gone through the painful process of updating all of the project directories for the Windows SDK include directory, lib directory, etc.

Visual Studio 2005 and 2008 are both smart enough to look in the version of the Windows SDK included with those compilers, but I'd never found a way to change the default version. Until now.

The Windows SDK comes with a utility called the Windows SDK Configuration Tool. You can find it in your Start menu.

When you run this, you can set the default SDK to be whichever version you want. Then Visual Studio will automatically reference that version of the SDK without any need to manually update project directories.

[Update 8/31/2011]
Visual Studio 2010 does not seem to pay attention to the Configuration Tool. Instead, this appears to be set on a project-by-project basis in Configuration Properties/Platform Toolset. After doing so, you may be able to fix some schizophrenic behavior by updating the MSBuild information too. Take a look at the following registry entries. (Thanks to the tip from http://geekswithblogs.net/rob/archive/2010/09/17/integrate-the-windows-sdk-v7.1-with-vs2010.aspx)

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\4.0
  • FrameworkSDKRoot (REG_SZ)
    • $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A@InstallationFolder)
  • SDK35ToolsPath (REG_SZ)
    • $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A\WinSDK-NetFx35Tools-x86@InstallationFolder)
  • SDK40ToolsPath (REG_SZ)
    • $(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A\WinSDK-NetFx40Tools-x86@InstallationFolder)