July 2008 - Posts

Visual C++ in Short: Determining whether a path refers to a file system object

If you’ve been programming Windows for a while (prior to Windows 2000) you may well have come across a number of techniques to determine whether a path refers to a file system object such as a file or directory.

One approach is to check the result of the CreateFile function but this approach has a number of pitfalls. Checking whether a path refers to a file system object should not change the state of the file system object, which CreateFile does in most cases. You can combat this by playing around with the various flags. For example, if you only specify FILE_READ_ATTRIBUTES as the desired access then the file’s last access date won’t be updated. Of course you may not have the necessary authorization to open the file handle at all. There are also other headaches associated with this approach such as remembering to close the file handle should the call to CreateFile succeed. Determining whether the file handle refers to a file or directory involves additional function calls.

Another solution is to use the FindFirstFile function but it gets a lot more data than you might need and you also need to remember to close the search handle.

The shell provides the PathFileExists function which is simpler than the approaches mentioned thus far but is limited in that it does not distinguish between files and directories. Still, if that’s good enough then here’s all you need to do:

const BOOL exists = PathFileExists(L"<some path>");

To be able to distinguish between files and directories involves checking the attributes of the file system object. The simplest way to get a file’s attributes is with the GetFileAttributes function introduced with Windows 2000 a long time ago (see comments). Of course if it fails to return the file attributes you can call the GetLastError function to find out why. That in turn provides a great way to determine whether the path refers to a file system object at all. It can also tell you other useful information such as whether the path is even valid.

The beauty of this model is that you get to decide just how much information you need. For example if you only want to know whether the path exists you can simply check whether GetFileAttributes returns INVALID_FILE_ATTRIBUTES or not. Alternatively you can distinguish between different classes of failure.

The following example shows a simple helper function that singles out the ability for the system to find the specified path from other failures. If a file system object exists it returns S_OK. If the path is well formed but the system cannot find the path or file then it returns S_FALSE. In all other cases it simply returns the specific failure as an HRESULT. It even optionally tells you whether the file system object is a directory or not.

HRESULT FileExists(PCWSTR fileName, bool* isDirectory)
{
   ASSERT(0 != fileName);

   const DWORD attributes = ::GetFileAttributes(fileName);

   if (INVALID_FILE_ATTRIBUTES == attributes)
   {
       const DWORD error = ::GetLastError();

       if (ERROR_FILE_NOT_FOUND == error ||
           ERROR_PATH_NOT_FOUND == error)
       {
           return S_FALSE;
       }
       else
       {
           return HRESULT_FROM_WIN32(error);
       }
   }

   if (0 != isDirectory)
   {
       *isDirectory = 0 != (FILE_ATTRIBUTE_DIRECTORY & attributes);
   }

   return S_OK;
}

You could for example identify syntax errors using the ERROR_INVALID_NAME error code:

bool isDirectory = false;
const HRESULT result = FileExists(L"<some path>", &isDirectory);

if (S_OK == result)
{
    if (isDirectory)
    {
        wprintf(L"Its a directory");
    }
    else
    {
        wprintf(L"Its a file");
    }
}
else if (S_FALSE == result)
{
    wprintf(L"Not found");
}
else
{
    if (HRESULT_FROM_WIN32(ERROR_INVALID_NAME) == result)
    {
        wprintf(L"The syntax is incorrect");
    }
    else
    {
        // Something else is wrong...
        wprintf(AtlGetErrorDescription(result));
    }
}

Incidentally, the PathFileExists function I mentioned above uses GetFileAttributes internally if it determines that you’re running on a supported version of Windows. In other words it’s a reasonable fallback if you need to support older operating systems.

There are also various shortcuts depending on what you intend to do with the path. For example if you just want to create a file and make sure it doesn’t already exist you can simply specify the CREATE_NEW creation disposition and the CreateFile function will fail if the specified file already exists.

If you’re looking for one of my previous articles here is a complete list of them for you to browse through.

Produce the highest quality screenshots with the least amount of effort! Use Window Clippings.

Posted by KennyKerr with 11 comment(s)

Windows with C++: Asynchronous WinHTTP

My latest Windows with C++ column in the August 2008 issue of MSDN Magazine is now online: Asynchronous WinHTTP.

This article had a bit of a rough time in the editing process and it’s not quite as polished as I would like. Nevertheless it’s still a good read and should give you a good starting point for building high performance and highly responsive HTTP client applications.

It was also heavily edited to meet the limited space requirements of print publication and some sections were dropped. One of them was a section on the positioning of WinHTTP compared to WinInet:

Veteran Windows developers may remember the Windows Internet (WinInet) API that has been around for years.  WinInet still provides a number of unique features such as support for FTP, credential caching, and user interface support. On the other hand it is not an ideal solution for service applications. It is also not suitable if your application needs to manage its own credentials, you don’t want to introduce user interface prompts, or don’t want to rely on Internet Explorer for proxy configuration.

The first paragraph in the Request Cancellation section was also edited to the point where it is incorrect and quite misleading. It should read:

WinHTTP provides a less error-prone model for asynchronous completion when compared to WinInet since your application is always notified of the completion of an operation through the callback function. On the hand, since worker threads are used to execute the callback function, cancelling a request does require some attention to detail.

Finally the section entitled Determining Proxy Settings was cut entirely from the print issue but is available as a sidebar in the online issue, although the associated screenshot was omitted.

Phew. Hopefully these minor issues will be straightened out eventually.

If you’re looking for one of my previous articles here is a complete list of them for you to browse through.

Produce the highest quality screenshots with the least amount of effort! Use Window Clippings.

Posted by KennyKerr with 5 comment(s)
Filed under:

Windows 2008 Remote Desktop Color Depth

One of the features of the Remote Desktop Protocol (RDP) 6.1 is the ability for clients to connect with a color depth of 32 bits per pixel (bpp). This allows alpha blending in a terminal session which in turn allows layered windows to work correctly. Although it's a bit of a bandwidth hog, it can be really handy for developers testing graphics applications remotely (or to take great screenshots remotely).

Although this works automatically when connecting remotely to Windows Vista it does not for Windows Server 2008 due to the aforementioned bandwidth hogging. Naturally Windows Server 2008 puts performance first. To enable this feature you need to use the Terminal Services Configuration tool (tsconfig.msc).

1. Right click on the desired connection (e.g. "RDP-Tcp") and click the "Properties" context menu item.

2. Select the "Client Settings" tab in the properties window.

3. Clear the "Limit Maximum Color Depth" check box or adjust the value as needed and click the OK button.

The next time an RDP 6.1 client connects and requests a color depth of 32 bpp, Terminal Services will deliver!

The latest version of RDP (at the time of writing) is 6.1 and is included with the following operating systems:

  • Windows Server 2008
  • Windows Vista Service Pack 1
  • Windows XP Service Pack 3 (client only)

Although I think the 32 bpp color depth support was added in version 6.0, it's usually best to get the latest version.

Produce the highest quality screenshots with the least amount of effort! Use Window Clippings.

Posted by KennyKerr with no comments
Filed under:

Visual C++ in Short: Converting between Unicode and UTF-8

The Windows SDK provides the WideCharToMultiByte function to convert a Unicode, or UTF-16, string (WCHAR*) to a character string (CHAR*) using a particular code page. Windows also provides the MultiByteToWideChar function to convert a character string from a particular code page to a Unicode string. These functions can be a bit daunting at first but unless you have a lot of legacy code or APIs to deal with you can just specify CP_UTF8 as the code page and these functions will convert between Unicode UTF-16 and UTF-8 formats. UTF-8 isn’t really a code page in the original sense but the API functions lives on and now provide support for UTF conversions.

ATL provides a set of class templates that wrap these functions to simplify conversions even further. It takes a fairly efficient and elegant approach to memory management (compared to previous versions of ATL) that should serve you well in most cases. CW2A is a typedef for the CW2AEX class template that wraps the WideCharToMultiByte function. Similarly, CA2W is a typedef for the CA2WEX class template that wraps the MultiByteToWideChar function.

In the example below I start with a Unicode string that includes the Greek capital letters for Alpha and Omega. The string is converted to UTF-8 with CW2A and then back to Unicode with CA2W. Be sure to specify CP_UTF8 as the second parameter in both cases otherwise ATL will use the current ANSI code page.

Keep in mind that although UTF-8 strings look like characters strings, you cannot rely on pointer arithmetic to subscript them as the characters may actually consume anywhere from one to four bytes. It’s also possible that Unicode characters may require more than two bytes should they fall in a range above U+FFFF. In general you should treat user input as opaque buffers.

#include <atlconv.h>
#include <atlstr.h>

#define ASSERT ATLASSERT

int main()
{
    const CStringW unicode1 = L"\x0391 and \x03A9"; // 'Alpha' and 'Omega'

    const CStringA utf8 = CW2A(unicode1, CP_UTF8);

    ASSERT(utf8.GetLength() > unicode1.GetLength());

    const CStringW unicode2 = CA2W(utf8, CP_UTF8);

    ASSERT(unicode1 == unicode2);
}

 

If you’re looking for one of my previous articles here is a complete list of them for you to browse through.

Produce the highest quality screenshots with the least amount of effort! Use Window Clippings.

Posted by KennyKerr with 2 comment(s)

Visual C++ in Short: Encoding and decoding with Base64

Base64 is a popular encoding to convert arbitrary data into a format that can be transmitted as an ASCII string. ATL provides a few functions that implement the Base64 specification.

To encode with Base64, start by allocating a buffer large enough to hold the Base64 string. The Base64EncodeGetRequiredLength function calculates how much space is required. The result of this function may be slightly larger than the actual Base64 string as it favors performance over accuracy.

The Base64Encode function performs the actual encoding. Its first two parameters specify the data to encode as well as the length in bytes. The third parameter identifies the destination buffer for the character string. The fourth parameter is an in/out parameter that on input specifies the size of the destination buffer and on output specifies the actual length of the Base64 string.

The following helper function wraps this logic and uses ATL’s string class to properly allocate and truncate the Base64 string buffer:

CStringA ToBase64(const void* bytes, int byteLength)
{
    ASSERT(0 != bytes);

    CStringA base64;
    int base64Length = Base64EncodeGetRequiredLength(byteLength);

    VERIFY(Base64Encode(static_cast<const BYTE*>(bytes),
                        byteLength,
                        base64.GetBufferSetLength(base64Length),
                        &base64Length));

    base64.ReleaseBufferSetLength(base64Length);
    return base64;
}

To decode with Base64, start by allocating a buffer large enough to hold the decoded data. If the data can have a variable length you can just allocate a byte array that is the same length as the Base64 string since the decoded data will always be somewhat smaller. ATL provides the Base64DecodeGetRequiredLength function but it simply returns its argument.

The Base64Decode function performs the actual decoding. Its first two parameters specify the Base64 string and its length. The third parameter identifies the destination buffer for the decoded data. The fourth parameter is an in/out parameter that on input specifies the size of the destination buffer and on output specifies the actual length of the decoded data.

The following example shows how to encode and decode the SYSTEM_INFO data structure:

#include <atlenc.h>
#include <atlstr.h>

#define ASSERT ATLASSERT
#define VERIFY ATLVERIFY

CStringA ToBase64(const void* bytes, int byteLength);

int main()
{
    SYSTEM_INFO info1 = { 0 };
    ::GetNativeSystemInfo(&info1);

    const CStringA base64 = ToBase64(&info1, sizeof(SYSTEM_INFO));

    SYSTEM_INFO info2 = { 0 };
    int byteLength = Base64DecodeGetRequiredLength(sizeof(SYSTEM_INFO));

    if (!Base64Decode(base64, base64.GetLength(), reinterpret_cast<BYTE*>(&info2), &byteLength))
    {
        // The string could not be decoded.
    }

    ASSERT(sizeof(SYSTEM_INFO) == byteLength);
    ASSERT(0 == memcmp(&info1, &info2, sizeof(SYSTEM_INFO)));
}

If you’re looking for one of my previous articles here is a complete list of them for you to browse through.

Produce the highest quality screenshots with the least amount of effort! Use Window Clippings.

Posted by KennyKerr with no comments

Visual C++ in Short: Converting between numbers and strings

C++ developers have a number of options available to them for converting between numbers and strings, few of which are very appealing. Most developers are familiar with the likes of atoi and itoa from the C Run-Time Library. The main problem is that these functions don’t have a coherent way of reporting errors. Although there have been some attempts to improve these functions, most notably the addition of the security enhancements introduced by Microsoft, they are still not very helpful.

Fortunately the Windows SDK includes a very comprehensive collection of functions that it inherited from OLE Automation to convert between variant-compatible types. These functions don’t actually require you to use variants or even initialize OLE or COM. They merely provide the functionality for converting between many of the types that you could store in a variant.

The functions are declared in OleAuto.h and take the form VarXxxFromYyy where Xxx is the desired type and Yyy is the original type of the data. You can use “Var[^ ]+From[^ (]+” to search for them from within Visual Studio.

 

The functions for converting strings to numbers are prototyped as follows:

HRESULT VarXxxFromStr(const WCHAR* string, LCID localeId, ULONG flags, T* number);

The source is a pointer to a Unicode string (and does not have to be a BSTR). The locale identifier affects how the string is interpreted. You can for example use the user’s regional settings as defined by the current thread’s locale identifier using the GetThreadLocale function. Alternatively you can specify LOCALE_INVARIANT if you need the conversions to be independent of the user’s locale. This might be the case if you’re using the text form of a number not to display to the user but rather to persist in some format like XML. The flags are mostly for controlling date and time conversions and should be zero in most other cases.

The following example shows how to convert a string to a double in a locale-independent manner:

double value = 0;

const HRESULT result = ::VarR8FromStr(L"1234.567",
                                      LOCALE_INVARIANT,
                                      0, // flags
                                      &value);

if (FAILED(result))
{
    // The HRESULT describes why the conversion failed,
    // e.g. DISP_E_TYPEMISMATCH, DISP_E_OVERFLOW
}

ASSERT(1234.567 == value);

The functions for converting numbers to strings are prototyped as follows:

HRESULT VarBstrFromYyy(T number, LCID localeId, ULONG flags, BSTR* string);

These functions all return the strings as BSTR values so the caller is responsible for freeing them using the SysFreeString function. A better approach is to use ATL’s CComBSTR wrapper class.

The following example shows how to convert a double to a string using the locale associated with the current thread and then converts the string back to a double again:

#include <atlbase.h>

#define ASSERT ATLASSERT

int main()
{
    double double1 = 1234.567;

    CComBSTR string;

    HRESULT result = ::VarBstrFromR8(double1,
                                     ::GetThreadLocale(),
                                     0, // flags
                                     &string);

    if (FAILED(result))
    {
        // The HRESULT describes why the conversion failed,
        // e.g. E_OUTOFMEMORY
    }

    double double2 = 0;

    result = ::VarR8FromStr(string,
                            ::GetThreadLocale(),
                            0, // flags
                            &double2);

    if (FAILED(result))
    {
        // The HRESULT describes why the conversion failed,
        // e.g. DISP_E_TYPEMISMATCH, DISP_E_OVERFLOW
    }

    ASSERT(double1 == double2);
}

Keep in mind that the thread locale can change at any time so you must not persist a localized version of a number as you may not be able to parse it later on. It is however useful for displaying and accepting input from the user.

If you’re looking for one of my previous articles here is a complete list of them for you to browse through.

Produce the highest quality screenshots with the least amount of effort! Use Window Clippings.

Posted by KennyKerr with 4 comment(s)

Visual C++ in Short: Regular Expressions

ATL includes a lightweight regular expression implementation. Although originally part of Visual C++, it is now included with the ATL Server download.

The CAtlRegExp class template implements the parser and matching engine. Its single template argument specifies the character traits such as CAtlRECharTraitsW for Unicode and CAtlRECharTraitsA for ANSI. The template argument also has a default argument based on whether or not _UNICODE is defined.

The CAtlREMatchContext class template provides an array of match groups for a successful match of a regular expression. It has the same default template argument as CAtlRegExp.

In the example below, CAtlRegExp’s Parse method is used to convert the regular expression into an instruction stream that is then used by the Match method to efficiently match the input string. Each match group is defined by a start and end pointer, defining the range of characters so that a copy does not have to be made if it is not needed.

The regular expression grammar is defined at the top of the atlrx.h header file.

#include <atlrx.h>
#include <atlstr.h>

#define ASSERT ATLASSERT

int main()
{
    CAtlRegExp<> regex;
    const REParseError status = regex.Parse(L"^/blog/{\\d\\d\\d\\d}/{\\d\\d?}/{\\d\\d?}/{\\a+}$");
    ASSERT(REPARSE_ERROR_OK == status);

    CAtlREMatchContext<> match;

    if (regex.Match(L"/blog/2008/7/16/SomePost", &match))
    {
        ASSERT(4 == match.m_uNumGroups);

        PCWSTR start = 0;
        PCWSTR end = 0;

        match.GetMatch(0, &start, &end);
        const UINT year = _wtoi(start);

        match.GetMatch(1, &start, &end);
        const UINT month = _wtoi(start);

        match.GetMatch(2, &start, &end);
        const UINT day = _wtoi(start);

        match.GetMatch(3, &start, &end);
        const CString name(start, end - start);

        wprintf(L"Year: %d\n", year);
        wprintf(L"Month: %d\n", month);
        wprintf(L"Day: %d\n", day);
        wprintf(L"Name: %s\n", name);
    }
}

If you’re looking for one of my previous articles here is a complete list of them for you to browse through.

Produce the highest quality screenshots with the least amount of effort! Use Window Clippings.

Posted by KennyKerr with 8 comment(s)

This and that

It’s been a while since I posted anything. I spent some time in South Africa. Increasingly I feel like it’s time to go home. If only it were that simple. We’ve also had a bit of a rough time here in England. I have also heard that a few people assumed that I’d be driving around in a Ferrari after the announcement about PlateSpin’s acquisition for $205 million in cash. I should just mention that I left PlateSpin about six months before the acquisition and did not get to share in the big payout for a variety of subtle and not so subtle reasons. So if you’ve enjoyed my articles feel free to support me by purchasing a license for Window Clippings – it will be much appreciated!   :)

There are a few more articles in the pipeline at MSDN Magazine. The first talks about writing asynchronous HTTP clients in native C++ (naturally). The second talks about high performance algorithms and cache-conscious design. I’ll post updates as they are released.

I’m also on track to release the next major version of Window Clippings in a few months. I’ve received a ton of feedback and am prioritizing new features and improvements to address the most popular requests.

As for this blog, I’m going to try something new. The articles I’ve posted on this blog have traditionally been on the long side (usually a few thousand words each). Although I enjoy writing them they do take a lot of time to put together. I’m going to try a little experiment and post a series of short articles (only a few hundred words each) and see how that works out. Please let me know what you think.

Posted by KennyKerr with 4 comment(s)
Filed under:
More Posts