Common Controls: Versions, Compatibility, WTL

An application appears to be not working in Windows XP in a weird way: rebar control appeared to fail showing up.

Where the application is expected to look much nicer with rebar control as a container for menu (implemented as command bar WTL control) and toolbar with buttons:

A WTL sample project generated by a Visual Studio wizard would never give such effect, and the bug was a combination of factors:

  1. An application built with a newer version of Windows SDK, which includes support for features (Windows Vista+ Common Controls) that are more recent than production environment (Windows XP); the application targets to Windows Vista+ environment too (_WIN32_WINNT >= 0x0600)
  2. Compatibility issues of Common Controls library
  3. WTL version (7.5), which did not yet include a workaround for the problem

The problem, which caused the bug directly was the REBARBANDINFO structure and its use as an argument with Common Controls API. As MSDN shows, the structure was amended twice with additional fields.

One of the way to support multiple versions of the structure definition, and to resolve compatibility issues, is to embed structure size into structure payload. In fact, REBARBANDINFO::cbSize member is there exactly for this reason.

The application is normally filling cbSize with the maximal known structure size and fills the rest of the fields respectively. The API is expected to be checking cbSize member and be detecting API version compatibility scenarios:

  1. cbSize holds exactly the value the API expects (that is, the maximal value known/defined to the API) – the simplest scenario where the API and the application are on the same page, both are using the same versions of the “protocol”/interface.
  2. cbSize is smaller than API can support – the API sees that it is dealing with a sort of legacy application which cannot utilize all available features, and the API acts respectively supporting the older part of the protocol, and keeping defaults or “old look” for the rest of implementation. This addresses backward compatibility: the newer API works with apps designed for older version of the API
  3. cbSize is greater then API can support – the API sees that the application is already aware of newer version API and is possibly requesting some of the missing features. The API might be ignoring the unsupported part in assumption that API evolution tool place keeping some compatibility in mind, and still do the best it can with the existing implementation. Or, the API might just fail to work.

The latter item #3 is the scenario here with rebar control. The application is using Windows Vista version of REBARBANDINFO structure and Windows XP implementation choses to completely fail.

While it does not seem to be directly a bug, this attitude is definitely not developer friendly: there is no reason for the control to not work in its best and default way. Having API acting this way, each developer using the API needs to take care of the situation explicitly: whenever Windows Vista enabled application needs to be able to run in Windows XP system, the code around REBARBANDINFO would look like this:

REBARBANDINFO BandInformation = { sizeof BandInformation, RBBIM_LPARAM };
#if _WIN32_WINNT >= 0x0600
if(GetOsVersion() < 0x00060000 || GetCommCtrlVersion() < 0x00060000) // pre-Vista, Common Controls pre-6.0
    BandInformation.cbSize = REBARBANDINFO_V6_SIZE;
#endif// _WIN32_WINNT >= 0x0600
const BOOL bGetBandInfoResult = Rebar.GetBandInfo(0, &BandInformation);

If the API was nicer to developers, the code would be plain and simple:

REBARBANDINFO BandInformation = { sizeof BandInformation, RBBIM_LPARAM };
const BOOL bGetBandInfoResult = Rebar.GetBandInfo(0, &BandInformation);

To address this problem, WTL 8.0 comes up with RunTimeHelper namespace and its SizeOf_REBARBANDINFO function. It takes care of details for the developer choosing the proper size of the structure on runtime. The code is being taken back to a simpler shape:

REBARBANDINFO BandInformation = { RunTimeHelper::SizeOf_REBARBANDINFO(), RBBIM_LPARAM };
const BOOL bGetBandInfoResult = Rebar.GetBandInfo(0, &BandInformation);

All in all:

  • be aware of compatibility issues (same scenario exists with other SDK structures: LVGROUP, LVTILEINFO, MCHITTESTINFO, NONCLIENTMETRICS and other).
  • use latest version of WTL to have things worked around for you where Microsoft developers were not kid enough to provide perfect API
  • be aware and take advantage of WTL’s RunTimeHelper class

GPS Location/Coordinate Converter: Fractional Seconds, More Shortcuts

This adds a small update to the recently published GPS Location/Coordinate Converter utility:

  • Seconds in Degrees, Minutes & Seconds notation are shown and are accepted as floating point numbers
  • More shortcuts to popular online map services (note that only Google Maps and Yandex Maps are still accepted as input via clipboard):
    • Bing Maps
    • Yahoo Maps
    • Open Street Map
    • WikiMapia

The latter makes the tool an easy to use converted between the services for a GPS POI.

A binary [Win32] and partial Visual C++ .NET 2010 partial source code are available from SVN.

Utility Clearance: Rasterize Font

RasterizeFont utility takes a font on the input (such as Windows .TTF – True-Type Font) and paints individual characters into bitmaps. Utility output includes separate bitmap (.BMP) files for requested characters and C++ source code of the bimap arrays (this was included into microcontroller project).

A configuration .INI file defines rasterizer parameters:

[General]
Width=48
Height=72
Horizontal Adjustment=1
Vertical Adjustment=0
Outline=1

[Font]
Face=Times New Roman
Height=48
Weight=1024

[Bitmaps]
PathTemplate=Character-%04x.bmp

And a list of characters of interest is passed as a command line argument.

const BYTE pnCharacter007a[] = // 0x007a z
{
    0x55, 0x55, 0x55,  // 01 01 01 01 01 01 01 01 01 01 01 01 
    0x55, 0x55, 0x55,  // 01 01 01 01 01 01 01 01 01 01 01 01 
    0x55, 0x55, 0x55,  // 01 01 01 01 01 01 01 01 01 01 01 01 
    0x54, 0x00, 0x05,  // 01 01 01 00 00 00 00 00 00 00 01 01 
    0x52, 0xaa, 0xa1,  // 01 01 00 10 10 10 10 10 10 10 00 01 
    0x52, 0x00, 0xa1,  // 01 01 00 10 00 00 00 00 10 10 00 01 
    0x54, 0x42, 0x85,  // 01 01 01 00 01 00 00 10 10 00 01 01 
    0x55, 0x2a, 0x15,  // 01 01 01 01 00 10 10 10 00 01 01 01 
    0x54, 0xa0, 0x45,  // 01 01 01 00 10 10 00 00 01 00 01 01 
    0x52, 0x80, 0x21,  // 01 01 00 10 10 00 00 00 00 10 00 01 
    0x52, 0xaa, 0xa1,  // 01 01 00 10 10 10 10 10 10 10 00 01 
    0x54, 0x00, 0x05,  // 01 01 01 00 00 00 00 00 00 00 01 01 
    0x55, 0x55, 0x55,  // 01 01 01 01 01 01 01 01 01 01 01 01 
    0x55, 0x55, 0x55,  // 01 01 01 01 01 01 01 01 01 01 01 01 
};

A binary [Win32] and Visual C++ .NET 2008 source code are available from SVN.

Utility Clearance: Logical Processor Information

LogicalProcessorInformation is a fronend GUI around GetLogicalProcessorInformation API and reveals CPU configuration of the system. If you are fine tuning stuff, you might want to know what sort of CPUs are powering the applications:

  • how many?
  • fully featured cores or HyperThreading technology?
  • mutli-processor configuration and how exactly physical processors are distributed over affinity mask

API and the application gets you the data as a user-friendly dump of GetLogicalProcessorInformation output and a summary of records at the bottom:

Continue reading →

You cannot remove RBBS_NOGRIPPER flag from rebar band

It is as stupid as it sounds: you can add RBBS_NOGRIPPER flag to a rebar band to implement “lock controls” feature, but as soon as you start removing it – you miserably fail.

A related thread on WTL group is dated year 2006. You can find the same dated 2003. Now it’s 2011 and it’s still here.

OK, it might be some bug in controlling code etc, but here is Control Spy 2.0. Here you go:

WTL does a cool trick to fool the bastard:

void LockBands(bool bLock)
{
    int nBandCount = GetBandCount();
    for(int i =0; i < nBandCount; i++)
    {
        REBARBANDINFO rbbi = { RunTimeHelper::SizeOf_REBARBANDINFO() };
        rbbi.fMask = RBBIM_STYLE;
        BOOL bRet = GetBandInfo(i, &rbbi);
        ATLASSERT(bRet);

        if((rbbi.fStyle & RBBS_GRIPPERALWAYS) == 0)
        {
            rbbi.fStyle |= RBBS_GRIPPERALWAYS;
            bRet = SetBandInfo(i, &rbbi);
            ATLASSERT(bRet);
            rbbi.fStyle &= ~RBBS_GRIPPERALWAYS;
        }
        if(bLock)
            rbbi.fStyle |= RBBS_NOGRIPPER;
        else
            rbbi.fStyle &= ~RBBS_NOGRIPPER;

        bRet = SetBandInfo(i, &rbbi);
        ATLASSERT(bRet);
    }
}

Pretty cool and works… if you have one rebar only. If you have another one in the same window (e.g. mine is at bottom) – you fail again.

A nasty workaround is to nudge hosting window by resizing it, followed by a full cycle of internal layout updates:

CRect Position;
ATLVERIFY(GetWindowRect(Position));
Position.bottom++;
ATLVERIFY(MoveWindow(Position));
Position.bottom--;
ATLVERIFY(MoveWindow(Position));

ProcessSnapshot: Create process minidump for port-mortem debugging

ProcessSnapshot is a utility to take a snapshot of process call stacks, and the snapshot taken is written into a human friendly text file.

ProcessSnapshot is taking process minidump files

Additionally to this, the utility has been given a capability to create process minidump files, on user request. The minidump files can be used with debugger to analyze the context of the process using feature rich debug environment, esp. Microsoft Visual Studio. To create a minidump for a process, check a corresponding box and press “Take a Dump” button. A file named “<process-image-name> – <date> <time>.dmp” will be created in the directory of the utility executable.

See also:

A binary [Win32, x64] and partial Visual C++ .NET 2008 source code are available from SVN.

YV12, Extended Video Renderer Strides, Private DMO and more

Recently it was the time to sort out an issue with a video DMO, which outputs YV12 video and in the same time is capable of supporting extended video strides in order to efficiently make a direct connection to Video Mixing Renderer Filters.

From past experience, I already knew that some bugs are definitely involved but their effect was yet unexplored. For a testbed application, I took good old FrameRateSample02 application, which generates multiple video feeds and routes it to video renderers:

FrameRateSample02 Application with New Choices

With new source video choices the application is capable of constructing filter graphs that use a private DMO (that is hosted inside the executable) wrapped with DMO Wrapper Filter, with a graph topology shown below:

Filter Graph with a Private DMO

Continue reading →