Thursday, December 15, 2011

WINDOW_MESSAGE_DEFINITION

WINDOW_MESSAGE_DEFINITION is used with #include to stamp out code for each window message. One example is when generator is defined.

template<typename WindowClassTag, typename Target>
struct generator {
  typedef
    typename generator_root < WindowClassTag, Target
#   define WINDOW_MESSAGE_DEFINE_BEGIN_GENERATOR
#   include "win32_messages.h"
#   undef WINDOW_MESSAGE_DEFINE_BEGIN_GENERATOR

#   define WINDOW_MESSAGE_DEFINE_END_GENERATOR
#   include "win32_messages.h"
#   undef WINDOW_MESSAGE_DEFINE_END_GENERATOR
    >::type
  type;
};

win32_messages.h contains a #define and #include for each supported window message.

#define WINDOW_MESSAGE_DEFINITION (PAINT,   Paint,   0, ())
#include "win32_message_define.h"

#define WINDOW_MESSAGE_DEFINITION (NCPAINT, NCPaint, 1, (HRGN))
#include "win32_message_define.h"

win32_message_define.h then uses that #define to stamp out code for that message. Here are the salient parts of win32_message_define for the generator definition.

#define WINDOW_MESSAGE_CAPITAL_NAME           TPLT_CALL(TPLT_EXTRACT, TPLT_ARGUMENTS_APPEND_LIST(4, WINDOW_MESSAGE_DEFINITION, 0))
#define WINDOW_MESSAGE_CASED_NAME             TPLT_CALL(TPLT_EXTRACT, TPLT_ARGUMENTS_APPEND_LIST(4, WINDOW_MESSAGE_DEFINITION, 1))
#define WINDOW_MESSAGE_PARAMETER_COUNT        TPLT_CALL(TPLT_EXTRACT, TPLT_ARGUMENTS_APPEND_LIST(4, WINDOW_MESSAGE_DEFINITION, 2))
#define WINDOW_MESSAGE_PARAMETER_LIST         TPLT_CALL(TPLT_EXTRACT, TPLT_ARGUMENTS_APPEND_LIST(4, WINDOW_MESSAGE_DEFINITION, 3))

#if defined(WINDOW_MESSAGE_DEFINE_BEGIN_GENERATOR)

#define WINDOW_MESSAGE_OPTIONAL TPLT_CALL(MAKE_IDENTIFIER_EXPLICIT, (optional, WINDOW_MESSAGE_CASED_NAME))

  , generator<WindowClassTag, Target, decltype(WINDOW_MESSAGE_OPTIONAL(instance_of<Target>::value, instance_of<Context<WindowClassTag>*>::value, 0)) 

#undef WINDOW_MESSAGE_OPTIONAL 

#elif defined(WINDOW_MESSAGE_DEFINE_END_GENERATOR)
  >
#endif

#undef WINDOW_MESSAGE_PARAMETER_LIST
#undef WINDOW_MESSAGE_PARAMETER_COUNT
#undef WINDOW_MESSAGE_CASED_NAME
#undef WINDOW_MESSAGE_CAPITAL_NAME
#undef WINDOW_MESSAGE_DEFINITION

First the arguments are pulled out of the WINDOW_MESSAGE_DEFINITION. Then one of the #if blocks is selected and the parameters are used to fill in the name of a message specific identifier. Now that the macro machinery is exposed, here is the generator definition that is stamped out.

template<typename WindowClassTag, typename Target>
struct generator {
  typedef
    typename generator_root < 
      WindowClassTag, 
      Target
      , generator<
          WindowClassTag, 
          Target, 
          decltype(
            optionalPaint(
              instance_of<Target>::value,
              instance_of<Context<WindowClassTag>*>::value, 
              0)) 

          , generator<
              WindowClassTag, 
              Target, 
              decltype(
                optionalNCPaint(
                  instance_of<Target>::value,
                  instance_of<Context<WindowClassTag>*>::value, 
                  0)) 
         >
       >
    >::type
  type;
};

The 'optional' methods are also generated via the same macros. The only piece missing is another #if block in win32_message_define.h That will be next up..

Thursday, December 8, 2011

window message dispatch generator

One goal for this dispatcher was to achieve pay-for-play performance characteristics. The generator builds a recursive type with a recursive dispatch function that only includes the message handling supported by the target. This produces a pretty concise if-else construct.

namespace detail {
template<typename WindowClassTag, typename Target>
struct generator_end
{
  typedef
    base<WindowClassTag, Target>
  type;
};

generator_end is used to terminate the recursive type being generated. base is defined previously but will be covered later.

template <
  typename WindowClassTag,
  typename Target,
  typename MessageChoice,
  typename Base = generator_end<WindowClassTag, Target >>
struct generator;

This is the prototype for generator, 2 specializations of generator are used to either add or omit a type from the recursive type.

template <
  typename WindowClassTag,
  typename Target,
  template <
    typename A,
    typename B,
    typename C > class MessageChoice,
  typename Base >
struct generator <
  WindowClassTag,
  Target,
  MessageChoice <
    WindowClassTag,
    Target,
    base<WindowClassTag, Target >> ,
  Base >
  : public Base
{
  typedef
    MessageChoice <
      WindowClassTag,
      Target,
      typename Base::type >
  type;
};

this specialization of generator matches when the target does support a message. It creates a type result using the supplied MessageChoice which is chained into the recursive type result (by changing the last template parameter to the result of the next recursed generator type result).

template <
  typename WindowClassTag,
  typename Target,
  typename Base >
struct generator <
  WindowClassTag,
  Target,
  nohandler,
  Base >
  : public Base
{
};

This specialization of generator matches when the target does not support the message (the nohandler class is already defined. nohandler will be described later.) There is no type defined here which ensures that no code will be generated for this message.

template <
  typename WindowClassTag,
  typename Target,
  typename Base >
struct generator_root
  : public Base
{
};
}

generator_root provides a container for the generator that allows the type to be stamped out by some macros.

template<typename WindowClassTag, typename Target>
struct generator {
  typedef
    typename detail::generator_root < WindowClassTag, Target
#   define WINDOW_MESSAGE_DEFINE_BEGIN_GENERATOR
#   include "win32_messages.h"
#   undef WINDOW_MESSAGE_DEFINE_BEGIN_GENERATOR

#   define WINDOW_MESSAGE_DEFINE_END_GENERATOR
#   include "win32_messages.h"
#   undef WINDOW_MESSAGE_DEFINE_END_GENERATOR
    >::type
  type;
};

This is how the type for a set of messages is created. This marco technique is complicated in order to allow the debugger to step through the dispatch code with source lines. WINDOW_MESSAGE_DEFINE_BEGIN_GENERATOR causes win32_messages.h to resolve to a recursive type for each message, while WINDOW_MESSAGE_DEFINE_END_GENERATOR causes win32_messages.h to resolve to a < for each type, this is required to finish the recursive generator definition.

Next is a look at the macro machinery..

Thursday, December 1, 2011

window message dispatcher

Time to look at the window message dispatcher. This is the third major implementation. so far.

Callers of dispatch should call DefWindowProc if this returns result.first == false.

One goal was to eliminate manual maintenance of a message-map from message id to function. Other goals included pay-for-use performance characteristics, code driven instead of data driven design, no virtual function calls and allow source debugging even in the macros (which are unfortunately required until C++ supports 'templated' names).

The current approach inspects the specified target class instance for a function matching each supported windows message. The parameters for the function are determined using the HANDLE_MSG_... macros from windowsx.h in the SDK. So if the target class has a function matching LRESULT OnPaint(const lib::wnd::Context<Tag>& context) then code to forward the WM_PAINT message to the function is included, otherwise the code is omitted.

template<typename WindowClassTag, typename Target>
std::pair<bool, LRESULT>
dispatch(
  Target target,
  const Context<WindowClassTag>& context)
{
  BOOL handled = FALSE;
  LRESULT result = 0;
  std::tie(handled, result) =
    generator<WindowClassTag, Target>::type(
        base<WindowClassTag, Target>(
            target, &context)).dispatch();

  if (!handled) {
    std::tie(handled, result) =
      optionalUnhandled(target, context);
  }

  return std::make_pair(
      handled ? true : false, result);
}

dispatch looks simple, it constructs a type stitched together in the generator detail class and calls the dispatch method on the class instance then if that function specifies that the message was not handled it calls optionalUnhandled. When the guts of the generator are exposed later that facade of simplicity will disintegrate. Until that time enjoy the appearance of simplicity.

struct UnhandledTag {};

The tag is used to increase the flexibility of the window_message_error_contract trait function.

template<typename WindowClassTag, typename Target>
std::pair<bool, LRESULT> optionalUnhandled(
  Target target,
  const Context<WindowClassTag>& context,
  decltype(
    cmn::instance_of<Target>::value->OnUnhandled(
      cmn::instance_of<Context<WindowClassTag>>::value)))
{
  LRESULT result = 0;
  window_message_error_contract(
    [&] {
      result = target->OnUnhandled(context);
    },
    context,
    UnhandledTag(),
    WindowClassTag()
  );
  return std::make_pair(true, result);
}

This optionalUnhandled overload is only included in the overload set if the decltype parameter can resolve the OnUnhandled(context) function on the target.

The window_message_error_contract function that must be provided by the target implementor can have many overloads in multiple namespaces. The two tag parameters allow this function to be provided once for the whole class or individually for each message type. The purpose of the error contract is for targets that enable exceptions to provide an overload that handles the exceptions.

Finally, the OnUnhandled method on target is called.

inline std::pair<bool, LRESULT> optionalUnhandled(...)
{
  return std::make_pair(false, 0);
}

If the first overload is not valid then this one is used to report that the message is still unhandled.

This introduced the optional method construct, this is the mechanism that is used to detect whether the target supports each potential message. In this case it detects wether the target is interested in the unhanded messages. Providing this function on the target allows the target to chain the message to another handler.

Next up is the generator..

Tuesday, November 29, 2011

WindowCallback

Time for a look at WindowCallback which implements a WNDPROC.

template<typename WindowClassTag>
LRESULT CALLBACK WindowCallback(
  HWND hWnd,
  UINT message,
  WPARAM wParam,
  LPARAM lParam) {
  __try {
    return detail::WindowCallbackSafe<WindowClassTag>(
        hWnd,
        message,
        wParam,
        lParam);
  } __except (FailFastFilter(GetExceptionInformation())) {
  }
  return 0;
}

Not much here, just set up an SEH exception filter that will prevent any exceptions from passing across the boundary from this module to the calling module.

namespace detail {

template<typename WindowClassTag>
LRESULT CALLBACK WindowCallbackSafe(
  HWND hWnd,
  UINT message,
  WPARAM wParam,
  LPARAM lParam) {

  bool handled = false;
  LRESULT result = 0;

  if (message == WM_NCCREATE) {
    auto existingType = optional_window_class_find(
      hWnd,
      WindowClassTag(),
      0);
    if (!existingType) {
      if (!optional_window_class_insert(
        hWnd,
        optional_window_class_construct(
          hWnd,
          reinterpret_cast<LPCREATESTRUCT>(lParam),
          WindowClassTag(),
          0),
        WindowClassTag(),
        0)) {
        return FALSE;
      }
    }
  }

window_class_find, window_class_insert, window_class_construct, window_class_erase and window_class_destroy are used to manage the lifetime of the implementation. The optional_ prefix refers to functions that provide a default behavior when the implementation does not choose to provide overloads of the functions. The defaults use new and delete for allocation and SetWindowLongPtr to store and retrieve the implementation. Each implementation can provide overloads of these functions to control allocation, construction and storage of that implementation.

This code will create and store the implementation in response to WM_NCCREATE. The attempt to find is here to guard against multiple WM_NCCREATE messages.

  auto type = optional_window_class_find(hWnd, WindowClassTag(), 0);

  ON_UNWIND_AUTO(
  [&] {
    if (type && message == WM_NCDESTROY) {
      optional_window_class_erase(hWnd, type, WindowClassTag(), 0);
      optional_window_class_destroy(hWnd, type, WindowClassTag(), 0);
    }
  }
  );

Here the code attempts to retrieve the implementation and setup a lambda function to destroy the implementation when WindowCallback exits. Using ON_UNWIND means that even a C++ exception will run the lambda.

  if (type) {
    Context<WindowClassTag> context = {hWnd, message, wParam, lParam};

    std::tie(handled, result) = msg::dispatch(type, context);
    if (handled) {
      return result;
    }
  }

  return DefWindowProc(hWnd, message, wParam, lParam);
}
}

The rest just calls the dispatch mechanism to forward the message to the correct function on the implementation - if it exists - and calls DefWindowProc otherwise.

template<typename WindowClassTag>
decltype(
  window_class_find(
    cmn::instance_of<HWND>::value,
    WindowClassTag()))
optional_window_class_find(HWND hwnd, WindowClassTag && , int)
{
  return window_class_find(hwnd, WindowClassTag());
}

template<typename WindowClassTag>
typename window_class<WindowClassTag>::traits::type*
optional_window_class_find(HWND hwnd, WindowClassTag && , ...)
{
  typedef
    typename window_class<WindowClassTag>::traits::type
  type;
  return reinterpret_cast<type*>(
    GetWindowLongPtr(hwnd, GWLP_USERDATA));
}

Using optional_window_class_find as an example of the optional_ pattern. The two functions both take the same parameters up until the last one. The last one is used so that when both functions are included in the overload set the compiler can break the tie. The compiler will choose to send 0 literal to an int parameter rather than ... but if the overload set only contains the function with the last parameter ends in ... then the compiler will select it without an error.

In this case the first function takes precedence only if the decltype can find a windows_class_find overload that takes these parameters. If it cannot the second function will be used to provide default functionality.

Next we will look at the magical msg dispatcher..

Thursday, November 24, 2011

window_class::Register

Continuing the look at window_class. here are the Register methods. Each one will initialize defaults for WNDCLASSEX then allow the window implementation to override the defaults by calling window_class_register via ADL. Then it will force the WNDPROC to WindowCallback and call Register.

template<typename WindowClassTag>
//static
ATOM window_class<WindowClassTag>::Register()
{
  WNDCLASSEX wcex = {};
  wcex.cbSize = sizeof(WNDCLASSEX);

  // defaults that can be overriden
  wcex.style = CS_HREDRAW | CS_VREDRAW;
  wcex.hInstance = GetCurrentInstance();
  wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);

  window_class_register(&wcex, tag());

  // not overridable
  wcex.lpfnWndProc = WindowCallback<WindowClassTag>;

  return RegisterClassEx(&wcex);
}

The default overload does the bare minimum

template<typename WindowClassTag>
template<typename T>
//static
ATOM window_class<WindowClassTag>::Register(T && t)
{
  WNDCLASSEX wcex = {};
  wcex.cbSize = sizeof(WNDCLASSEX);

  // defaults that can be overriden
  wcex.style = CS_HREDRAW | CS_VREDRAW;
  wcex.hInstance = GetCurrentInstance();
  wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);

  window_class_register(std::forward<T>(t), &wcex, tag());

  // not overridable
  wcex.lpfnWndProc = WindowCallback<WindowClassTag>;

  return RegisterClassEx(&wcex);
}

This overload will accept a parameter, any parameter that the implementation desires to require, it could even be a fully filled out WNDCLASSEX that is just copied over the defaults.

Tuesday, November 22, 2011

win32 window_class

I have been working on a library for building win32 windows. MFC and WTL were both great designs at the time that they were introduced, but C++ has moved on.

My goals for this library:

  • I wanted to enable the building of window controls like the common controls in windows
  • I wanted to draw a distinct line between the window implementation and window usage
  • I wanted to remove the window message map from the implementation
  • I wanted to eliminate virtual functions from the implementation
  • I wanted to enable exception based implementations without requiring them

Code Walkthrough

template<typename WindowClassTag>
struct traits {
  typedef
    decltype(window_class_traits(WindowClassTag()))
  type;
};

traits encapsulates the lookup of a type that provides traits. the lookup is done using ADL (argument dependent lookup) using the WindowClassTag to cause the compiler to find the window_class_traits function that is in the same namespace as the provided WindowClassTag. The type returned from this is arbitrary as long as it has the typedefs that window_class makes reference to.

template<typename WindowClassTag>
LRESULT CALLBACK WindowCallback(
  HWND hWnd,
  UINT message,
  WPARAM wParam,
  LPARAM lParam);

This is the WNDPROC implementation where all the magic happens.

template<typename WindowClassTag>
class window_class {
public:
  typedef
    WindowClassTag
  tag;

  typedef
    typename traits<tag>::type
  traits;

start of the declaration of window_class including some simple typedefs to shorten usage inside window_class

  static ATOM Register();

  template<typename T>
  static ATOM Register(T && t);

overloads of the static Register function. when called these will register the window class.

private:
  ~window_class();
  window_class();
  window_class(window_class&);
  window_class& operator=(window_class&);
};

the end of window_class which prevents any instances of window_class from being made, this is a static only class.

The next post will show the Register implementations..

Tuesday, November 15, 2011

walk-through of RootWindow from scratch program

Last time I posted a port of Raymond Chen's scratch program. I mentioned that I had some goals for the design of the window library. One of those goals was to follow the intended window lifetime model. Most of the controls built into windows work by registering window classes that will allocate memory to store their state on the first message (usually WM_NCCREATE) and deallocate that state on the last message (usually WM_NCDESTROY). The window handle returned from CreateWindow is then used to send messages to get or set state.

In most existing libraries there is a single class with both the window handle and the state and an instance of the class is allocated and then passed to CreateWindow. Deallocation becomes challenging. If it is deallocated on WM_NCDESTROY then there is a risk that the object will be accessed after the destructor has run. In addition there is always the risk that delete could be called while the window is still trying to send messages.

Following the pattern used by the built-in controls results in a much safer lifetime model.

The following walkthrough will explain how each line contributes to the pattern:

Add a namespace where the implementation details of the window can be placed

namespace RootWindow {

This struct tag is the glue that is used to leverage ADL to stitch all the pieces of the window together.

struct tag {};

Adding a typedef for the Context just reduces typing. Notice the tag is used to make this Context unique to RootWindow.

typedef
  l::wnd::Context<tag>
    Context;

The struct window is allocated by the library on WM_NCCREATE to provide the runtime state for the window. in addition to the state it also provides a function for each window message it wishes to receive
The child member is there to mirror Raymond's scratch program as is the empty OnCreate.
OnPaint and OnPrintClient are in the base class of Raymond's scratch and I could have placed them in a common location as well, but I have not settled on the best place for them so they are here for now.

Notice that there is no message map. The library uses templates to detect which methods exist on struct window and only handle those. The rest go to DefWindowProc.

struct window
{
  l::wr::unique_close_window child;

  LRESULT OnCreate(const Context& , LPCREATESTRUCT) {
    return 0;
  }

  LRESULT OnSize(const Context& , UINT , int cx, int cy) {
    if (child) {
      SetWindowPos(
        child.get(), NULL,
        0, 0, cx, cy,
        SWP_NOZORDER | SWP_NOACTIVATE);
    }
    return 0;
  }

  LRESULT PaintContent(PAINTSTRUCT&) {
    return 0;
  }

  LRESULT OnPaint(const Context& context) {
    PAINTSTRUCT ps = {};
    BeginPaint(context.window, &ps);
    l::wr::unique_gdi_end_paint ender(
      std::make_pair(context.window, &ps));
    return PaintContent(ps);
  }

  LRESULT OnPrintClient(const Context& context, HDC hdc, DWORD) {
    PAINTSTRUCT ps = {};
    ps.hdc = hdc;
    GetClientRect(context.window, &ps.rcPaint);
    return PaintContent(ps);
  }

  LRESULT OnNCDestroy(const Context&) {
    PostQuitMessage(0);
    return 0;
  }
};

This declares a function that has no implementation. This function is used by the library to locate the window class using the tag struct. Since it is never called and is only referenced in a decltype expression there is no need for an implementation.

l::wnd::window_class_traits_builder<window>
window_class_traits(tag &&);

This function does need an implementation. The library calls this function to allow the window registration defaults to be changed. The library uses the tag to find this function.

void window_class_register(
  PCWSTR windowClass,
  WNDCLASSEX* wcex,
  tag &&) {
  wcex->style         = 0;
  wcex->hIcon         = NULL;
  wcex->hCursor       = LoadCursor(NULL, IDC_ARROW);
  wcex->lpszMenuName  = NULL;
  wcex->lpszClassName = windowClass;
}
}

This function is found using the tag as well. The library calls this function for each message that it dispatches. This function provides user-specified error handling. If this function does not catch exceptions the library will exit the process if an exception is thrown. This allows the library to be used in code that does not support exceptions as well (by skipping the try/catches).

template<typename Function, typename MessageTag>
void window_message_error_contract(
  Function && function,
  RootWindow::Context& ,
  MessageTag && ,
  RootWindow::tag &&)
{
  try {
    std::forward<Function>(function)();
  } catch (std::bad_alloc &&) {
  } catch (unique_winerror::exception &&) {
  } catch (unique_hresult::exception &&) {
  }
}

This typedef actually stitches all the previous pieces into the final type. the window_class is given the tag after which it uses the tag to search out all the pieces and build a WndProc that will create a struct window and start calling OnCreate etc..

typedef
  l::wnd::window_class<RootWindow::tag>
    RootWindowClass;

Thursday, November 10, 2011

a scratch program

I have been working on a library for building win32 windows. MFC and WTL were both great designs at the time that they were introduced, but C++ has moved on. Then there is Raymond Chen's new(2005) C++ scratch program which eschews libraries and builds a simple base class with virtual functions

One of the things that bothers me about all the existing libraries is that they mix two distinct objects with separate lifetimes into one object with incoherent lifetime. I will go into more detail on this and other design decisions in additional posts.

So here is a port of Raymond's scratch program using my window library.

#define STRICT
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#define UNICODE
#define _UNICODE

#include <windows.h>
#include <windowsx.h>
#include <ole2.h>
#include <commctrl.h>
#include <shlwapi.h>
#include <shlobj.h>
#include <shellapi.h>

#include <new>
#include <utility>
#include <memory>
#include <type_traits>
#include <tuple>
#include <string>
#include <vector>

#define LIBRARIES_NAMESPACE mylib
#include "..\libraries\libraries.h"
namespace l = LIBRARIES_NAMESPACE;

void unique_error_report_initiated(
  DWORD value,
  unique_winerror::tag &&)
{
  static DWORD anchor;
  anchor = value;
}

void unique_error_report_reset(
  DWORD value,
  unique_winerror::tag &&)
{
  static DWORD anchor;
  anchor = value;
}

void unique_error_report_initiated(
  HRESULT value,
  unique_hresult::tag &&)
{
  static HRESULT anchor;
  anchor = value;
}

void unique_error_report_reset(
  HRESULT value,
  unique_hresult::tag &&)
{
  static HRESULT anchor;
  anchor = value;
}

namespace RootWindow {
struct tag {};

typedef
  l::wnd::Context<tag>
    Context;

struct window
{
  l::wr::unique_close_window child;

  LRESULT OnCreate(const Context& , LPCREATESTRUCT) {
    return 0;
  }

  LRESULT OnSize(const Context& , UINT , int cx, int cy) {
    if (child) {
      SetWindowPos(
        child.get(), NULL,
        0, 0, cx, cy,
        SWP_NOZORDER | SWP_NOACTIVATE);
    }
    return 0;
  }

  LRESULT PaintContent(PAINTSTRUCT&) {
    return 0;
  }

  LRESULT OnPaint(const Context& context) {
    PAINTSTRUCT ps = {};
    BeginPaint(context.window, &ps);
    l::wr::unique_gdi_end_paint ender(
      std::make_pair(context.window, &ps));
    return PaintContent(ps);
  }

  LRESULT OnPrintClient(const Context& context, HDC hdc, DWORD) {
    PAINTSTRUCT ps = {};
    ps.hdc = hdc;
    GetClientRect(context.window, &ps.rcPaint);
    return PaintContent(ps);
  }

  LRESULT OnNCDestroy(const Context&) {
    PostQuitMessage(0);
    return 0;
  }
};

l::wnd::window_class_traits_builder<window>
window_class_traits(tag &&);

void window_class_register(
  PCWSTR windowClass,
  WNDCLASSEX* wcex,
  tag &&) {
  wcex->style         = 0;
  wcex->hIcon         = NULL;
  wcex->hCursor       = LoadCursor(NULL, IDC_ARROW);
  wcex->lpszMenuName  = NULL;
  wcex->lpszClassName = windowClass;
}
}

template<typename Function, typename MessageTag>
void window_message_error_contract(
  Function && function,
  RootWindow::Context& ,
  MessageTag && ,
  RootWindow::tag &&)
{
  try {
    std::forward<Function>(function)();
  } catch (std::bad_alloc &&) {
  } catch (unique_winerror::exception &&) {
  } catch (unique_hresult::exception &&) {
  }
}

typedef
  l::wnd::window_class<RootWindow::tag>
    RootWindowClass;

int PASCAL
wWinMain(HINSTANCE hinst, HINSTANCE, LPWSTR, int nShowCmd)
{
  unique_hresult hr;

  hr.reset(CoInitialize(NULL));
  if (!hr) {
    return FALSE;
  }
  ON_UNWIND_AUTO([&] {CoUninitialize();});

  InitCommonControls();

  RootWindowClass::Register(L"Scratch");

  unique_winerror winerror;
  l::wr::unique_close_window window;

  std::tie(winerror, window) =
    l::wr::winerror_and_close_window(
        CreateWindow(
            L"Scratch", L"Scratch",
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT, CW_USEDEFAULT,
            CW_USEDEFAULT, CW_USEDEFAULT,
            NULL, NULL,
            hinst,
            NULL));

  if (!winerror || !window) {
    return winerror.get();
  }

  ShowWindow(window.get(), nShowCmd);

  MSG msg = {};
  while (GetMessage(&msg, NULL, 0, 0)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
  return 0;
}

Tuesday, November 8, 2011

more on optional traits via ADL

I posted earlier about a way to provide optional functionality through traits. I used operator [] as the example. As I have been using the library I found some issues with that approach. The main issue was that operator[] is not a template method, being on a templates class is not enough. This meant that using SFINAE to remove the function entirely when the trait was not specified was not possible. Another issue was that some compilers would complain if auto was used on free-functions. These are both addressed now, here is the latest.
template<typename TypeTag, typename ResourceType>
decltype(unique_t_at(
    instance_of<ResourceType>::value,
    instance_of<size_t>::value,
    TypeTag()))
optional_unique_t_at(
  ResourceType && resource,
  size_t index,
  int)
{
  return unique_t_at(
      std::forward<ResourceType>(resource),
      index,
      TypeTag());
}

struct no_indexing_support {};

template<typename TypeTag>
no_indexing_support
optional_unique_t_at(...)
{
  return no_indexing_support();
}

template<typename TypeTag>
class unique_t {
private:
  typedef
  decltype(optional_unique_t_at<TypeTag>(
    instance_of<type>::value,
    instance_of<size_t>::value,
    0))
  optional_at_result;
public:
  ...
  optional_at_result operator[](
    size_t at) {
    return optional_unique_t_at<TypeTag>(
      t,
      at,
      0);
  }
private:
  type t;
};

Lines 1-24 take care of routing to the trait implementation, when it exists, and a default that provides a suitable error when used. The auto keyword is not used, as a consequence we cannot use the parameters and must synthesize the values used in the decltype. These free-functions are templates and are therefore able to use SFINAE. Here we can see most of the adjustments that were needed to get optional traits working.

Thursday, November 3, 2011

Synology

First a quick recap of my past data losses. I have had 8 drive failures in the last decade. After the first one that caused painful data loss (even the recovery company couldn't retrieve anything) I bgan buying HD's in pairs with RAID controllers mirroring them. This has saved me many times.

I decided some years ago to buy a NAS with some serious storage to hold my music (lossless compression). I bought a Synology CubeStation and 3 500GB seagate drives and set up in RAID 5. This worried me ever since because sometimes the failures are controller failures not drive failures.

A couple of months ago I started to hear fan noise from the Synology and knew it was time to replace it. It took a while (and some additional hardware failures) for that to reach the top of my list. But I finally ordered a new RAID device.

One of the best things about the Synology was the constant updates and improvements. They took the NVidia/Apple model and kept similar software for all their devices so my old device kept getting addition features, bug fixes and even a couple of complete UI redesigns while I had it.

I decided to try one of those just before the new device arrived. The UI warned me to upload the file to the Synology a different way, but I decided to go for it. The update indeed failed, then the UI stopped responding and then the device started flashing an orange light. It was inaccessible.

I opened a support ticket and they told me to go through the normal install process from a PC connected by ethernet. I balked at this because I did not want to lose data. However, I tried it and it failed. Then I unplugged all the drives and tried again. it failed. Then I connected all the drives and tried again (at their prompting).

Each time I ran the install it listed the steps like 'format system partition' and 'format data partition' - very scary to me. But the last time I tried it went all the way through and when it got to the 'format data partition' step it skipped it! When it all came back it had my data intact. I am quite impressed and very thankful!

Tuesday, November 1, 2011

FAIL_FAST

In Windows 7 an new weapon in the fight against bugs was released in the form of RaiseFailFastException

In a world where Windows Error Reporting (WER) collects each crash and reports it with a minidump. FAIL_FAST is essential to finding and fixing bugs quickly. Instead of laboring for a repro, just open the minidump and it points to the line of code that failed and usually has enough state to determine the cause.

FAIL_FAST should be used to report bugs in code. Transient or environmental failures like no-memory or access-denied are not suited for reporting via FAIL_FAST, rather things like 'I do not understand this enum value' or 'I did not expect this error value'

#define FAIL_FAST_FILTER() \
  __except(FailFastFilter(GetExceptionInformation())) \
  { \
  } do {} while(0,0)

inline
LONG WINAPI FailFastFilter(
  __in  struct _EXCEPTION_POINTERS* exceptionInfo)
{
  RaiseFailFastException(
    exceptionInfo - > ExceptionRecord,
    exceptionInfo - > ContextRecord,
    0);
  return EXCEPTION_CONTINUE_SEARCH;
}

template<typename Function>
auto FailFastOnThrow(
  Function && function) -> decltype(
      std::forward<Function>(function)())
{
  //
  // __ try must be isolated in its own
  // function in order for the compiler
  // to reason about C++ unwind in the
  // calling and called functions.
  //
  __try {
    return std::forward <Function >(function)();
  }
  FAIL_FAST_FILTER();
}

#define FAIL_FAST_ON_THROW(Function) \
  FailFastOnThrow((Function))

#define FAIL_FAST(Code) \
  FAIL_FAST_ON_THROW(
    [&]{ \
      RaiseException( \
        (Code), \
        EXCEPTION_NONCONTINUABLE, \
        0, \
        nullptr \
      ); \
    } \
  )

Thursday, October 27, 2011

range copy

The range library proposal for the std library included copy_range which required that the dest range have a constructor that took begin and end iterators. This was not applicable to C struct ranges like UNICODE_STRING.

I decided to fix this by following the pattern for the begin and end free-functions. A free-function named copy calls a free-function named range_copy via ADL that can be overloaded for each Range type. The default range_copy has the same behavior that the proposed copy_range provided, but now other range_copy overloads can be written.

UNICODE_STRING usage

This snippet shows some of the operations now enabled.

auto helloRange = as_literal(L"hello");
auto title = copy<std::wstring>(helloRange);

auto unicodeHello = copy<UNICODE_STRING>(helloRange);
auto stringRange = make_range(unicodeHello);
auto unicodeTitle = copy<UNICODE_STRING>(
    make_range_raw(title)
    );
stringRange = make_range(unicodeTitle);
  • line 1 will make a range<const wchar_t*> that points to the static string array.
  • line 2 will make a std::wstring that holds a copy of the static string array.
  • line 4 will make a UNICODE_STRING that points to the static string array.
  • line 5 will make a range<PWSTR> that points to the static string array.
  • line 6 will make a UNICODE_STRING that points to the wstring copy of the static string array.
  • line 9 will make a range<PWSTR> that points to the wstring copy of the static string array.

Implementation

maintained here

template< class RangeTo, class RangeFrom >
auto range_copy(RangeFrom && r, RangeTo*) ->
decltype(
  RangeTo(
      begin(std::forward<RangeFrom>(r)),
      end(std::forward<RangeFrom>(r))
  )
)
{
  return RangeTo(
      begin(std::forward<RangeFrom>(r)),
      end(std::forward<RangeFrom>(r))
      );
}

template< class RangeTo, class RangeFrom >
auto copy(RangeFrom && r) ->
decltype(
  range_copy(
      std::forward<RangeFrom>(r),
      reinterpret_cast<RangeTo*>(nullptr)
  )
)
{
  return range_copy(
      std::forward<RangeFrom>(r),
      reinterpret_cast<RangeTo*>(nullptr)
      );
}

line 27 passes in a nullptr cast to a RangeTo* this dummy parameter is ugly but required to enable Argument-Dependent-Lookup (ADL) when range_copy is implemented in RangeTo's namespace. I considered using the parameter rather than returning a RangeTo by-value, but then RangeTo must be default-constructable since the copy free-function would have to have one on the stack in order to pass a pointer into range_copy. The current definition allows the overload for RangeTo to use any constructor.

UNICODE_STRING implementation

Now enabling UNICODE_STRING for use with the range library requires only this

// enable UNICODE_STRING <-> range

PWSTR range_begin(const UNICODE_STRING& string)
{
  return string.Buffer;
}

PWSTR range_end(const UNICODE_STRING& string)
{
  return string.Buffer + (string.Length / 2);
}

template< class RangeFrom >
UNICODE_STRING range_copy(
  RangeFrom && r,
  UNICODE_STRING*
)
{
  UNICODE_STRING result = {};

  result.Buffer = const_cast<PWSTR>(
      begin(std::forward<RangeFrom>(r))
      );
  result.Length = size_cast<USHORT>(
      size(std::forward<RangeFrom>(r)) * 2
      );
  result.MaximumLength = size_cast<USHORT>(
      size(std::forward<RangeFrom>(r)) * 2
      );

  return result;
}

Tuesday, October 25, 2011

range size_cast

The range library proposal for the std library included size which calculated the distance between begin(r) and end(r). This value usually ends up in a ptrdiff_t. I often need to put the size of a range into much smaller size types when using C APIs and C structs. Just adding a static_cast is no sufficient as I not only want to cast the type, but ensure that the value fits.

I added size_cast. It requires an explicit ReturnType template parameter. Then it can verify that the value will fit and only then do a static_cast to coerce the value into the ResultType.

The next post will demonstrate some usage.

Implementation

maintained here

template< class ResultType, class InputType >
ResultType
size_cast(InputType size)
{
  const static size_t
  bitsOfPositiveRepresentationInResultType =
    (sizeof(ResultType) * 8) -
    static_cast<ResultType>(
        std::is_signed<ResultType>::value);
  const static size_t
  bitsOfPositiveRepresentationInInputType =
    (sizeof(InputType) * 8) -
    static_cast<InputType>(
        std::is_signed<InputType>::value);
  typedef
  std::conditional <
  bitsOfPositiveRepresentationInResultType <
  bitsOfPositiveRepresentationInInputType,
  InputType,
  ResultType
  >::type
  check_type;
  check_type size_check = static_cast<check_type>(size);
  FAIL_FAST_IF(
    (false,
      (std::is_signed<InputType>::value && size < 0)) ||
        (size_check >> (
          bitsOfPositiveRepresentationInResultType - 1)) != 0,
    ERROR_INVALID_PARAMETER
  );
  return static_cast<ResultType>(size);
}

Thursday, October 20, 2011

make_range_raw

I wrote a range library some years ago and then found a proposal to include a range library in the std library.

I adopted the proposed library and over time I have added additional features to ease usage of C APIs. One feature I added is make_range_raw.

make_range works by requiring that the Range passed in has support for the begin and end free-functions. This produces range<Iterator> where Iterator is a raw pointer for built-in arrays but uses the iterator type defined by the Range when it is a collection like vector or wstring. This is the desired behavior for make_range but when trying to interface between collections and C APIs it would be better to access the raw pointer for contiguous array collections like vector and wstring.

make_raw_range requires that the collection support raw access via operator []. Using &r[0] for begin and &r[0] + size(r) for end produces range<Iterator> where Iterator is always a raw pointer. (for well behaved collections this is true. vector<bool> is not well behaved)

Implementation

maintained here

template< class Range >
auto
make_range_raw(Range && r) ->
decltype(
  make_range(
      &r[0],
      &r[0] + size(r)
  )
)
{
  if (size(r) == 0) {
    decltype(
      make_range(
          &r[0],
          &r[0] + size(r)
      )
    ) result;
    return result;
  }
  return make_range(
      &r[0],
      &r[0] + size(r)
      );
}

template< class Range >
auto
make_range_raw(
  Range && r,
  typename
  range_difference<Range>::type advance_begin,
  typename
  range_difference<Range>::type advance_end
) ->
decltype(
  make_range(
      &r[0],
      &r[0] + size(r)
  )
)
{
  decltype(
    make_range(
        &r[0],
        &r[0] + size(r)
    )
  ) result;
  if (size(r) != 0) {
    result = make_range(
        &r[0],
        &r[0] + size(r)
        );
  }
  result.advance_begin(advance_begin);
  result.advance_end(advance_end);
  return result;
}

Tuesday, October 18, 2011

catch(…) is harmful and should be avoided

A common use of catch(...), even in the STD library implementation, is to free objects or to return to a known state on failure.

catch(...) has no information about the exception and therefore there is no way to reason about whether the code in the catch block will corrupt the process. Thus any code in a catch(...) is a potential danger to the process and the data it manages.

Whenever an exception is thrown and the search for a catch encounters a catch(...) block it must run all the destructors for the code inside the matching try to get the stack back to the correct state to run the catch block. At best this modifies the state, when it doesn't corrupt it. Then the catch block is likely to immediately rethrow the exception with the state at the most relevant part of the stack (where the throw occurred) erased.

This erasure is particularly unwanted when the exception is ultimately not handled and a Windows Error Report is generated with a dump of the state after the unhelpful catch(...) erased the part that would be most important to determine how to fix the bug.

Windows Error Reporting (WER) has changed the way I write code. I try to exit the process quickly (FAIL_FAST) whenever I reach an unexpected state. When there are no catch(...) blocks in the way I get great bugs generated directly from the WER with no repro necessary and I quickly issue a fix.

The good thing is that none of the catch(...) blocks are needed and that the replacements do not corrupt the state when the exception type is not known to the call stack. The common case where you might use catch(...) to free an allocation or restore state can be replaced by an unwinder. In the case where catch(...) is used to suppress an exception it should be replaced with a FAIL_FAST_ON_THROW([]{});. This will not suppress the exception (which as described earlier invites data corruption), instead when an exception that is not expected and handled reaches this barrier a WER will be generated and the process will exit without any corruption.

These boundaries can be enforced using error contract functions:

template<typename Function>
HRESULT HResultErrorContract(Function && function)
{
  HRESULT result = S_OK;
  FAIL_FAST_ON_THROW(
  [&] {
    // any C++ exception that is uncaught or any SEH
    // will cause the process to exit
    try
    {
      unique_hresult hresult = (
        std::forward<Function>(function)());
      result = hresult.get();
    } catch (const std::bad_alloc&) {
      result = E_OUTOFMEMORY;
    } catch (const unique_winerror::exception& e) {
      result = HRESULT_FROM_WIN32(e.get());
    } catch (const unique_hresult::exception& e) {
      result = e.get();
    }
  }
  );
  return result;
}

HRESULT MyDllExport()
{
  // no exception can get past
  // HResultErrorContract
  return HResultErrorContract(
  [&]() -> unique_hresult {
    // It is safe to throw C++ exceptions
    unique_hresult hresult;
    // RestoreState is only called on failure
    ON_UNWIND(unwindWork, []{ RestoreState(); });
    hresult = Work();
    if (hresult.ok()) {
      unwindWork.Dismiss();
    }
    return hresult;
  }
}

Thursday, October 13, 2011

error contract functions

In code for Windows there are many places that are boundaries across which C++ exceptions cannot safely travel.

The most accurate way to describe the boundaries is to say that C++ exceptions cannot be sent across modules (exe and all and sys are all examples of modules). It may not be completely clear from that statement when a module boundary is crossed. Here are some examples that should help reason about when a module boundary is being crossed. The most straight forward situation is when a function is exported from a dll so that it can be called from a different module. but it can get considerably more abstract when you think of dll methods that return COM interfaces or structs containing function pointers. Then add all the PROC's used in Windows programming. WNDPROC, DLGPROC and so many other PROC's are all functions in one module called from a different module.

Any C++ exceptions that occur in these boundary functions must be stopped before the calling module try's to process them. The problem is that exception types are not always the same in each module. if the calling module try's to process an exception from a different module it could be that the type has different members or that the size of the members is different and the constructors, destructors and other methods compiled into the calling module are the wrong methods for an instance of the type that was constructed in the called module. Crashes or data corruption will ensue.

When building all these boundary functions it becomes important to centralize the catch blocks used to convert exceptions to errors and the FAIL_FAST for uncaught exceptions. Without centralization there is a lot of duplicated code.

With lambdas and perfect-forwarding using r-value references we can build error contract functions that will centralize the boundary contract for errors in one function and apply that contract to many functions. Here is an implementation of a error contract function for use with boundary functions that return HRESULT.

template<typename Function>
HRESULT HResultErrorContract(Function && function)
{
  HRESULT result = S_OK;
  FAIL_FAST_ON_THROW(
  [&] {
    // any C++ exception that is uncaught or any SEH
    // will cause the process to exit
    try
    {
      unique_hresult hresult = (
        std::forward<Function>(function)());
      result = hresult.get();
    } catch (const std::bad_alloc&) {
      result = E_OUTOFMEMORY;
    } catch (const unique_winerror::exception& e) {
      result = HRESULT_FROM_WIN32(e.get());
    } catch (const unique_hresult::exception& e) {
      result = e.get();
    }
  }
  );
  return result;
}

HRESULT MyDllExport()
{
  // no exception can get past
  // HResultErrorContract
  return HResultErrorContract(
  [&]() -> unique_hresult {
    // It is safe to throw C++ exceptions
    unique_hresult hresult;
    hresult = Work();
    return hresult;
  }
}

error contract functions are specific to the module they are used in, they are not candidates for a general shared template library. This is because each module uses different libraries and therefore has different exceptions that must be caught and translated.

Tuesday, October 11, 2011

C++ exception implementation on Windows

On windows c++ exceptions are implemented using an exception facility provided by the OS. The OS exception system (Structured Exception Handling or SEH) does not have the same semantics as C++ exception handling.

Windows SEH works in C or assembly code as well as C++. the C++ compiler and the OS are both involved. SEH is used to report many runtime errors and logic errors in code. Often they are unrecoverable. Access Violation, Stack Overflow, RPC errors, are all reported using SEH exceptions. Here is some code that uses SEH

LONG WINAPI MyExceptionFilter(
  __in  struct _EXCEPTION_POINTERS *ExceptionInfo,
  __in DWORD ExceptionCode
)
{
    // code in an exception filter must be 
    // very robust, careful and have minimal 
    // dependencies. often t\filters are run 
    // at times of extreme duress or with 
    // malicious intent

    //
    // must return one of these three values:

    // EXCEPTION_CONTINUE_EXECUTION
    //   re execute the instruction that 
    //   triggered the exception. if it
    //   fails again the new exception 
    //   will be marked
    //   EXCEPTION_NONCONTINUABLE_EXCEPTION

    // EXCEPTION_CONTINUE_SEARCH
    //   call the next registered 
    //   exception filter

    // EXCEPTION_EXECUTE_HANDLER
    //   run all the finally blocks for
    //   nested try's and then runs the 
    //   __except block and then runs 
    //   the finally block and then 
    //   continues after the __try/
    //   __except/__finally

    return EXCEPTION_CONTINUE_SEARCH;
}

void* ptr = nullptr;
__try
{
  ptr = malloc(1);
  if (!ptr) {
    __leave;
  }
  Work(ptr); // might AV or overflow stack, etc..
  // or explicitly call RaiseException() to 
  // raise an SEH
} __except (
    // registers MyExceptionFilter for any SEH
    // that occurs in the __try
    MyExceptionFilter(
      GetExceptionInformation(),
      GetExceptionCode()))
{
  // MyExceptionFilter returned 
  // EXCEPTION_EXECUTE_HANDLER
}
__finally()
{
  // the stack is unwinding due to a return
  // or an exception that is handled here or
  // up the stack from here
  if (ptr) {
    free(ptr);
  }
}

Hopefully it is obvious that an SEH exception will not cause C++ destructors to be called without some more work. The C++ compiler supports __try/__except/__finally and also supports try/catch, but not in the same function. Also, the C++ compiler will not allow __try/__except/__finally to be used in a function that has a local variable with a destructor.

Disclaimer - this is inaccurate yet provides a mental picture suitable for reasoning about the intersection of SEH and C++. - When the C++ compiler sees a try it inserts a __try, and an __except with a filter that is passed information about the catch clauses and catch blocks and destructors in scope. The C++ compiler replaces each throw with a RaiseException() that stores the exception object in the SEH ExceptionInformation. Then the SEH mechanism calls the registered filter and the filter tries to match the catch block type to the exception object type. If a catch block matches the filter calls the appropriate destructors and the appropriate catch block and then returns EXCEPTION_EXECUTE_HANDLER to continue after the catch block.

The C++ compiler also does not implement throw() semantics. Using what we know we can implement those semantics:

#define FAIL_FAST_FILTER() \
  __except(FailFastFilter(GetExceptionInformation())) \
  { \
  } do {} while(0,0)

inline
LONG WINAPI FailFastFilter(
  __in  struct _EXCEPTION_POINTERS* exceptionInfo)
{
  RaiseFailFastException(
    exceptionInfo - > ExceptionRecord,
    exceptionInfo - > ContextRecord,
    0);
  return EXCEPTION_CONTINUE_SEARCH;
}

template<typename Function>
auto FailFastOnThrow(
  Function && function) -> decltype(
      std::forward<Function>(function)())
{
  //
  // __ try must be isolated in its own
  // function in order for the compiler
  // to reason about C++ unwind in the
  // calling and called functions.
  //
  __try {
    return std::forward <Function >(function)();
  }
  FAIL_FAST_FILTER();
}

#define FAIL_FAST_ON_THROW(Function) \
  FailFastOnThrow((Function))

HRESULT MyDllExport()
{
  HRESULT result = S_OK;
  FAIL_FAST_ON_THROW(
  [&] {
    // any C++ exception that is uncaught or any SEH
    // will cause the process to exit
    try
    {
      unique_hresult hresult;
      hresult = Work();
      result = hresult.get();
    } catch (const std::bad_alloc&) {
      result = E_OUTOFMEMORY;
    } catch (const unique_winerror::exception& e) {
      result = HRESULT_FROM_WIN32(e.get());
    } catch (const unique_hresult::exception& e) {
      result = e.get();
    }
  }
  );
  return result;
}

Next time we will build error contract functions to reduce the amount of code in each export.

Thursday, October 6, 2011

all smart ptr's should have a replace method

A lot of C++ code ends up interfacing with C functions. std::vector and std::basic_string have been constructed to make it possible to use them with c functions (basic_string::c_str vector::data and vector::operator[])

Smart pointers, however do not interface well with c code. I believe that c function interfacing is unsupported due to concern that address() is too dangerous to expose. While interfacing with c code does require the same return value that address would return, it does not require the same semantics.

The implementation of replace() would call reset() and then return address(). This would mean that the user could not accidentally leak a pointer by using replace()

Here is some code that shows how std::unique_ptr interacts with a c function now and how it would work if it had replace().

struct CoTask_deleter {
  void operator()(void* expired) {
    CoTaskMemFree(expired);
  }
};

unique_hresult hresult;

{
  //
  // without replace
  //
  LPOLESTR rawString = nullptr;
  std::unique_ptr<OLECHAR, CoTask_deleter> string;
  hresult.reset(StringFromCLSID(GUID_NULL, &rawString));
  // memory allocation is not 'owned'
  // any mistake from here through the
  // unique_ptr reset will result in a
  // leak
  if (hresult.ok()) {
    string.reset(raw_string);
    raw_string = nullptr;
    // now the memory is safely owned
  }
}

{
  //
  // with replace
  //
  std::unique_ptr<OLECHAR, CoTask_deleter> string;
  hresult.reset(
    StringFromCLSID(
        GUID_NULL,
        string.replace()));
  // there is no point when the memory is not owned
}

if (!hresult)
{
  return;
}

Tuesday, October 4, 2011

template policies via ADL

I wrote a range library some years ago and then found a proposal to include a range library in the std library.

I liked the design and decided to implement the proposal. One of the coolest features of the proposal is how ADL and decltype are used to implement traits or policies.

Since that time I have continued to refine the use of ADL and decltype to produce policies with vastly improved flexibility, stability and usability then anything I have seen before.

For example (Note: for space reasons this code is incomplete and won't compile. A working version of unique_t called unique_resource is available here) if we start with an existing smart-pointer that has a policy trait for the type and the way to close the type:

// policy based type
template<typename T, typename Close>
class unique_t_classic;

// user code using that type
template<typename T, typename Close>
void function(unique_t_classic<T, Close>& t);

Then at some future time we wish to add an index trait to enable operator[] usage:

// new policy
template<
  typename T, 
  typename Close, 
  typename Index=DefaultIndex<T>>
class unique_t_classic;

Now all the code that was dependent on the original policy set will fail to compile.
Here is the way I would express this functionality today:

template<typename TypeTag>
class unique_t;

template<typename Tag>
void function(unique_t<Tag>& t);

Now we can explore three different implementations of this with different policies without changing any of the above. The initial implementation might look like this.

template<typename TypeTag>
class unique_t
{
public:
  // these functions are looked up via ADL
  // thus this will pick up the definition
  // of unique_t_invalid_value from whatever
  // namespace TypeTag is in, and since TypeTag
  // is not the actual type (in database terms
  // it is a dataless key to the traits) the
  // user controls which namespace the
  // traits are in
  typedef decltype(unique_t_invalid_value(TypeTag()))
  type;
  //...
  void reset() {
    if (t != unique_t_invalid_value(TypeTag())) {
      unique_t_reset(t, TypeTag());
      t = unique_t_invalid_value(TypeTag());
    }
  }
private:
  type t;
};

A user might write code like this:

// Usability is provided by allowing simple
// and static definitions of specific 
// template instantiations
namespace detail
{
namespace file
{
struct tag {};
HANDLE unique_t_invalid_value(tag &&)
{
  return INVALID_HANDLE_VALUE;
}
void unique_t_reset(HANDLE value, tag &&)
{
  make_winerror_if(!CloseHandle(value)).suppress();
}
}
}
typedef unique_t<detail::file::tag>
unique_file;

Now it is time to make some changes to unique.
This will add optional indexing capability:

template<typename TypeTag>
class unique_t
{
public:
  ...
  auto operator[](
    size_t at) -> decltype(
        unique_t_index(at, TypeTag())) {
    return unique_t_index(at, TypeTag());
  }
private:
  type t;
};

unique_file still works as before. It does not support operator[] because it does not define unique_t_index.
More dramatic changes can be made without breaking existing code. This will make the type trait optionally independent of the return value of unique_t_invalid_value:

//
// This is a completely optional type
// it merely provides a succinct way 
// to create a type with a typedef 
// of the correct name 
//
template<typename T>
struct unique_t_traits_builder {
  typedef T
  type;
};

namespace detail
{
//
// this implements the optional part.
//
// notice that neither of these functions
// are implemented, they are only used in 
// declspec so no implementation is referenced
//
// the users definition of unique_t_traits
// needs no implementation either.
//

// this is used if the user supplied a 
// unique_t_traits for the TypeTag
template<typename TypeTag>
auto resolve_unique_t_traits(
  size_t) -> decltype(unique_t_traits(TypeTag()));

// the is used if the user only supplied 
// unique_t_invalid_value for the TypeTag
template<typename TypeTag>
unique_t_traits_builder<unique_t_invalid_value(TypeTag())>
resolve_unique_t_traits(...);
}

template<typename TypeTag>
class unique_t
{
public:
  typedef decltype(
    detail::resolve_unique_t_traits(TypeTag()))
  traits;

  typedef typename traits::type
  type;
  // ...
  void reset() {
    if (t != unique_t_invalid_value(TypeTag())) {
      unique_t_reset(t, TypeTag());
      t = unique_t_invalid_value(TypeTag());
    }
  }
private:
  type t;
};

Viola! no change to user code was required even though the implementation changed dramatically and the traits are different. This provides stability and flexibility that previous policy patterns lacked.

Thursday, September 29, 2011

unique_error

I work in places that abjure exceptions in most of the code. I have spent years writing both error-code and exception based error handling and building libraries for both environments. With some simple building blocks error-codes and exceptions can be joined such that each library can be written agnostic to exceptions and allow each caller of the library to choose whether to throw or pass error codes. These also implement certain exception features; such as requiring explicit checking of error codes.

One building block is unique_error.

unique_error serves much the same function as the std::system_error but with additional features and eschewing some things that blocked my adoption of std::system_error. unique_error does not require that all the error values of a type be redefined. It uses traits discovered by ADL to specify the behavior. It terminates the program if an error is set and then not checked. unique_error is also similar to unique_ptr in that it treats an error like a resource.

Here is the complete definition of unique_winerror:

namespace unique_winerror_def
{
struct tag {};

// found by ADL via the tag&& parameter
inline bool unique_error_ok(DWORD winerror, tag &&)
{
  return winerror == ERROR_SUCCESS;
}

// found by ADL via the tag&& parameter
inline DWORD unique_error_default(tag &&)
{
  return ERROR_SUCCESS;
}
}

//
// implementations of these must be included
// in the final module
//
void unique_error_report_initiated(
  DWORD value,
  unique_winerror_def::tag &&);
void unique_error_report_reset(
  DWORD value,
  unique_winerror_def::tag &&);

typedef unique_error<unique_winerror_def::tag>
unique_winerror;

inline unique_winerror make_winerror_if(BOOL is_last_error)
{
  unique_winerror result;
  if (is_last_error) {
    return std::move(result.reset(GetLastError()));
  }
  return std::move(result);
}

inline
unique_winerror::static_error winerror_cast(DWORD raw)
{
  return unique_winerror::cast(raw);
}

Using unique_winerror

CreateEvent example

Starting from a previous post we can now improve the code further:

namespace Win32
{
template<typename Resource, Resource InvalidValue>
std::pair<unique_winerror, Resource>
WinerrorAndResource(Resource resource)
{
  return std::make_pair(
      make_winerror_if(Resource == InvalidValue),
      Resource);
}

namespace Event
{
inline auto EventAndWinerror(
  HANDLE apiResult) -> decltype(
      WinerrorAndResource<HANDLE, nullptr>(
          apiResult))
{
  return WinerrorAndResource<HANDLE, nullptr>(
      apiResult);
}
}
}

// now you can write this
namespace we = Win32::Event;
unique_winerror winerror;
HANDLE event = nullptr;

std::tie(
  winerror,
  event) = we::EventAndWinerror(
      CreateEvent(
          nullptr
          make(we::Reset::Manual),
          make(we::Value::Reset),
          nullptr));
if (!winerror)
{
  return;
}

LoadString example

The complexities of LoadString for arbitrary sized strings is encapsulated here:

inline
unique_winerror
LoadStringRaw(
  HINSTANCE instance,
  UINT id,
  const range<WCHAR*>& space,
  range<WCHAR*>* spaceUsed,
  size_t* spaceRequested)
{
  if (spaceUsed) {
    *spaceUsed = space;
    spaceUsed->advance_end(-space.size());
  }

  if (spaceRequested) {
    *spaceRequested = space.size();
  }

  SetLastError(ERROR_SUCCESS);

  int loadResult = LoadStringW(
      instance,
      id,
      space.begin(),
      space.size());

  auto winerror = make_winerror_if(TRUE);

  if (loadResult >= 0) {
    if ((loadResult + 1) < space.size()) {
      if (winerror.ok()) {
        *spaceUsed = space;
        spaceUsed->advance_end(
          loadResult - space.size());
      }
    } else {
      *spaceRequested = std::max<size_t>(
          3,
          static_cast<size_t>(space.size() * 1.5));

      if (winerror.ok()) {
        winerror = winerror_cast(ERROR_MORE_DATA);
      }
    }
  } else {
    if (winerror.ok()) {
      winerror = winerror_cast(ERROR_UNIDENTIFIED_ERROR);
    }
  }

  return winerror;
}

inline
std::wstring
LoadStdString(
  HINSTANCE instance,
  UINT id,
  size_t sizeLimit = 2048,
  size_t initialSize = 80)
{
  unique_winerror winerror;
  std::wstring result;
  RANGE_NAMESPACE::range<WCHAR*> spaceUsed;
  size_t spaceRequested = initialSize;

  while (spaceRequested < sizeLimit) {
    result.resize(spaceRequested);
    winerror = LoadStringRaw(
        instance,
        id,
        make_range_raw(result),
        &spaceUsed,
        &spaceRequested);
    if (winerror != winerror_cast(ERROR_MORE_DATA)) {
      winerror.throw_if();
      break;
    }
    winerror.suppress();
    continue;
  }

  return std::move(result);
}

std::wstring title;

title = LoadStdString(
    hInstance,
    IDS_APP_TITLE);

Implementation

Maintained here.

template<typename ErrorTag>
class unique_error
{
public:
  typedef unique_error
  this_type;

  typedef ErrorTag
  tag;

  typedef decltype(unique_error_default(tag()))
  type;

  class static_error
  {
  private:
    type value;
  };

  static static_error cast(type raw);
  static this_type make(type raw);
  static this_type make(const static_error& other);

  ~unique_error();

  unique_error();
  unique_error(static_error other);
  unique_error(unique_error && other);
  unique_error(const unique_error& other);

  void swap(unique_error& other);
  unique_error& operator=(unique_error other);

  operator
  typename unspecified_bool<this_type>::type() const;

  this_type& reset();
  this_type& reset(type raw);
  type release();

  type get() const;
  bool try_ok() const;
  bool ok() const;

  const this_type& suppress() const;
  this_type& suppress();

  void throw_if(const std::string& message) const;
  void throw_if(const char* message = NULL) const;

private:
  type value;
  mutable Disposition::type disposition;
};

Tuesday, September 27, 2011

an unwinder should be in the standard library

The Unwinder is an implementation of the ScopeGuard pattern. The Unwinder is a class with a constructor that accepts a function and then runs that function in its destructor. The class has a method to dismiss the Unwinder. A dismissed unwinder will not run the function in its destructor. The Unwinder can be used as a generic implementation of the RRID (Resource Release Is Destruction) pattern.

With the addition of lambdas, auto and declspec to the C++ language the Unwinder becomes so trivial to use that in many cases no RAII class should be written. The implementation I use is called Unwinder.

Unwinder usage

int main()
{
  CRITICAL_SECTION lock = {};
  if (
    !InitializeCriticalSectionAndSpinCount(
        &lock,
        0x00000400)) {
    terminate();
  }

  ON_UNWIND_AUTO([&] {DeleteCriticalSection(&lock);});

  EnterCriticalSection(&lock);
  ON_UNWIND_AUTO([&] {LeaveCriticalSection(&lock);});

  // protected region

  {
    LeaveCriticalSection(&lock);
    ON_UNWIND_AUTO([&] {EnterCriticalSection(&lock);});

    // unprotected region
  }

  // protected region

  return 0;
}

Comparisons


This actually intersects with discussions of code style. There are many ways to structure function implementations. Of those there are a few common patterns that produce predictable results. Here are two structures; goto-cleanup and nested-scope:

int main()
{
  //
  // The goto-cleanup structure
  //

  CRITICAL_SECTION lock = {};
  BOOL inLock = FALSE;

  if (
    !InitializeCriticalSectionAndSpinCount(
        &lock,
        0x00000400)) {
    terminate();
  }

  EnterCriticalSection(&lock);
  inLock = TRUE;

  // protected region

  LeaveCriticalSection(&lock);
  inLock = FALSE;

  // unprotected region

  EnterCriticalSection(&lock);
  inLock = TRUE;

  // protected region

Cleanup:
  if (inLock) {
    LeaveCriticalSection(&lock);
    inLock = FALSE;
  }
  DeleteCriticalSection(&lock);
  return 0;
}
int main()
{
  //
  // The nested-scope structure
  //

  CRITICAL_SECTION lock = {};

  if (
    !!InitializeCriticalSectionAndSpinCount(
        &lock,
        0x00000400)) {
    {
      EnterCriticalSection(&lock);

      // protected region

      {
        LeaveCriticalSection(&lock);

        // unprotected region

        EnterCriticalSection(&lock);
      }

      // protected region

      LeaveCriticalSection(&lock);
    }

    DeleteCriticalSection(&lock);
  }

  return 0;
}

In both of these structures the code to undo or release an action is located a great distance from the action. Thus to read or verify the code one must scroll back and forth, even in short functions one must bounce visually all over the code to understand it.
Also, both of these are exception phobic. They require that exceptions are not used in the code.
Using the Unwinder, one is able to read left->right, top->bottom with no need to bounce. Each action is immediately followed by the undo. Even better, the code becomes exception agnostic, it will behave correctly with or without exceptions.

Implementation


The Unwinder is so subtle to build that it really should be in the standard. I have been through at least 4 implementations to reach my current one. One of the previous implementations was contributed by a coworker. His was based on std::function and did not require a macro to use correctly. After using it in my code for a while I pointed out that std::function could throw on construction and that this required changes to the implementation and made usage very tricky. After a year of periodic reviews of and changes to that implementation we finally decided to deprecate it, it was just too subtle and risky. The implementation included here does require macros, but is exception agnostic. This implementation is maintained here.

//
// common tools
//

#define MAKE_IDENTIFIER_EXPLICIT_PASTER(Prefix, Suffix) \
  Prefix ## Suffix

#define MAKE_IDENTIFIER_EXPLICIT(Prefix, Suffix) \
  MAKE_IDENTIFIER_EXPLICIT_PASTER(Prefix, Suffix)

#define MAKE_IDENTIFIER(Prefix) \
  MAKE_IDENTIFIER_EXPLICIT(Prefix, __LINE__)

#define FAIL_FAST_FILTER() \
  __except(FailFastFilter(GetExceptionInformation())) \
  { \
  } do {} while(0,0)

inline
LONG WINAPI FailFastFilter(
  __in  struct _EXCEPTION_POINTERS* exceptionInfo)
{
  RaiseFailFastException(
    exceptionInfo->ExceptionRecord,
    exceptionInfo->ContextRecord,
    0);
  return EXCEPTION_CONTINUE_SEARCH;
}

template<typename Function>
auto FailFastOnThrow(
  Function && function) -> decltype(
      std::forward<Function>(function)())
{
  //
  // __ try must be isolated in its own
  // function in order for the compiler
  // to reason about C++ unwind in the
  // calling and called functions.
  //
  __try {
    return std::forward<Function>(function)();
  }
  FAIL_FAST_FILTER();
}

#define FAIL_FAST_ON_THROW(Function) \
  FailFastOnThrow((Function))

//
// unwinder
//

template<typename Function>
class unwinder
{
public:
  ~unwinder() {
    if (!!function) {
      FAIL_FAST_ON_THROW([&] {(*function)();});
    }
  }

  explicit unwinder(Function* functionArg)
    : function(functionArg) {
  }

  void dismiss() {
    function = nullptr;
  }

private:
  unwinder();
  unwinder(const unwinder&);
  unwinder& operator=(const unwinder&);

  Function* function;
};

#define ON_UNWIND(Name, Function) \
  ON_UNWIND_EXPLICIT( \
      uwfunc_ ## Name, \
      Name, \
      Function)

#define ON_UNWIND_AUTO(Function) \
  ON_UNWIND_EXPLICIT( \
      MAKE_IDENTIFIER(uwfunc_), \
      MAKE_IDENTIFIER(unwind_), \
      Function)

#define ON_UNWIND_EXPLICIT(FunctionName, UnwinderName, Function) \
  auto FunctionName = (Function); \
  unwinder<decltype(FunctionName)> \
  UnwinderName(std::addressof(FunctionName))

Thursday, September 22, 2011

I loathe bool function parameters

What does HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL); do?
In this case bManualReset = TRUE and bInitialState = FALSE.

By combining patterns that I observed in the code of various co-workers and adding some of my own, I built the following pattern for making enums that can be used for parameters with any number of states, including bool.

namespace Win32
{
namespace Event
{
namespace Reset
{
enum type {
  // ensures that zero
  // initialized is invalid
  Invalid = 0,

  Manual,
  Auto,

  End,
  Begin = Manual
};

inline BOOL make(type from)
{
  switch (from) {
  case Manual:
    return TRUE;
  case Auto:
    return FALSE;
  default:
    terminate();
  };
}
}

namespace Value
{
enum type {
  // ensures that zero
  // initialized is invalid
  Invalid = 0,

  Set,
  Reset,

  End,
  Begin = Set
};

inline BOOL make(type from)
{
  switch (from) {
  case Set:
    return TRUE;
  case Reset:
    return FALSE;
  default:
    terminate();
  };
}
}
}
}

// now you can write this
// (the make functions are found via ADL)
namespace we = Win32::Event;
HANDLE event = nullptr;
event = CreateEvent(
    nullptr,
    make(we::Reset::Manual),
    make(we::Value::Reset),
    nullptr
    );

A remaining issue is that the compiler cannot enforce the type safety on the result of the make functions, so reversing the bManualReset and bInitialState parameters will compile without error and lie to readers of the code.

This issue does not plague functions that are defined to use the enum types. So, with a little more work:

namespace Win32
{
namespace Event
{
inline HANDLE Create(
  Reset::type reset,
  Value::type value,
  LPCWSTR name = nullptr
)
{
  return CreateEventW(
      nullptr,
      make(reset),
      make(value),
      name);
}

inline HANDLE Create(
  LPSECURITY_ATTRIBUTES security,
  Reset::type reset,
  Value::type value,
  LPCWSTR name = nullptr
)
{
  return CreateEventW(
      security,
      make(reset),
      make(value),
      name);
}
}
}

// now you can write this
namespace we = Win32::Event;
HANDLE event = nullptr;
event = we::Create(
    we::Reset::Manual,
    we::Value::Reset
    );

I general I try to avoid recreating named values and wrapping Api functions. Both the set of values and the valid inputs to the Api can change over time which requires me to chase the current definitions. Also, these change the surface of the Api, which creates an additional learning curve for callers. In this case where the api takes two BOOL parameters, I think the enums are valuable, but I am still somewhat ambivalent about the inline functions.

Tuesday, September 20, 2011

NTSTATUS

NTSTATUS was defined for code native to the Windows NT operating system. It was a part of the very clean separations built between the core OS and the various subsystems where user code was expected to run (POSIX, WIN32, WIN16/DOS, OS/2). Over time it has begun to leak into code in the WIN32 subsystem. One example of leakage is the BCrypt Api's.

Just including ntstatus.h and windows.h together produces errors:

main.cpp
#include <windows.h>
#include <winternl.h>
#include <ntstatus.h>

int main()
{
  return 0;
}

>cl main.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

main.cpp
[redacted]ntstatus.h(147) 
    : warning C4005: 'STATUS_WAIT_0' 
        : macro redefinition
    [redacted]winnt.h(1983) 
        : see previous definition of 'STATUS_WAIT_0'
...

I spent some hours recently tracking down an incantation that would allow ntstatus.h to be included without the errors, the following was the result:

#define WIN32_NO_STATUS
#include <windows.h>
#undef WIN32_NO_STATUS

#include <winternl.h>
#include <ntstatus.h>

NTSTATUS defines 2bits to hold four severity levels, SUCCESS, INFORMATION, WARNING, ERROR.
There are 12bits set aside for Facilities, which are used to create feature-specific error codes. Within each facility is 16bits to define codes specific to that facility.
FACILITY_NULL contains generic codes like STATUS_SUCCESS.
FACILITY_NTWIN32 contains all the WINERROR codes.

Checking NTSTATUS values must be done via the NT_SUCCESS(ntstatus), NT_INFORMATION(ntstatus), NT_WARNING(ntstatus) or NT_ERROR(ntstatus) macros.

NTSTATUS Usage

NTSTATUS ApiReturningNtStatus(HANDLE handle)
{
  if (handle == INVALID_HANDLE_VALUE) {
    return STATUS_INVALID_PARAMETER;
  }
  return STATUS_SUCCESS;
}

NTSTATUS ntstatus = STATUS_SUCCESS;
HANDLE handle = INVALID_HANDLE_VALUE;
ntstatus = ApiReturningNtStatus(handle);
if (!NT_SUCCESS(ntstatus))
{
  printf("ApiReturningNtStatus returned %x", ntstatus);
  exit();
}

Conversions to NTSTATUS

HRESULT = S_OK;
NTSTATUS ntstatus = STATUS_SUCCESS;
if (hr & FACILITY_NT_BIT)
{
  ntstatus = hr & ~FACTILITY_NT_BIT;
} else if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
{
  ntstatus = NTSTATUS_FROM_WIN32(HRESULT_CODE(hr));
} else if (SUCCEEDED(hr))
{
  ntstatus = STATUS_SUCCESS;
} else
{
  ntstatus = STATUS_UNSUCCESSFUL;
}

DWORD winerror = ERROR_SUCCESS;
NTSTATUS ntstatus = STATUS_SUCCESS;
ntstatus = NTSTATUS_FROM_WIN32(winerror);

Conversions from NTSTATUS

NTSTATUS ntstatus = STATUS_SUCCESS;
HRESULT hr = HRESULT_FROM_NT(ntstatus);

NTSTATUS ntstatus = STATUS_SUCCESS;
DWORD winerror = RtlNtStatusToDosError(ntstatus);
if (winerror == ERROR_MR_MID_NOT_FOUND)
{
  // there is no conversion
  return ERROR_UNIDENTIFIED_ERROR;
#if 0
  // The following is common, but doesn't work out well
  // especially when combined with HRESULT_FROM_WIN32
  // and NTSTATUS_FROM_WIN32
  return ntstatus;
#endif
}

Thursday, September 15, 2011

HRESULT

HRESULT is the highest fidelity error code of the three big ones (WINERROR, NTSTATUS and HRESULT). Both of the other error types can be converted, without any information loss, into an HRESULT via HRESULT_FROM_WIN32 and HRESULT_FROM_NT.

HRESULT was defined as the error type for COM functions to return.

HRESULT and NTSTATUS have a similar structure but very different sets of values.
1bit holds 2 severity levels, SUCCESS, ERROR.
1bit is used to allow HRESULT_FROM_NT to store a full NTSTATUS in an HRESULT. The define for this bit is FACILITY_NT_BIT.
There are 12bits set aside for Facilities, which are used to create feature-specific error codes. Within each facility is 16bits to define codes specific to that facility.
FACILITY_NULL contains generic codes like S_OK, E_FAIL and S_FALSE.
FACILITY_WIN32 contains all the WINERROR codes.

Checking HRESULT values must be done via the SUCCEEDED(hr) or FAILED(hr) macros.

HRESULT Usage

HRESULT ApiReturningHresult(HANDLE handle)
{
  if (handle == INVALID_HANDLE_VALUE) {
    return E_HANDLE;
  }
  return S_OK;
}

HRESULT hr = S_OK;
HANDLE handle = INVALID_HANDLE_VALUE;
hr = ApiReturningHresult(handle);
if (FAILED(hr))
{
  printf("ApiReturningHresult returned %x", hr);
  exit();
}

Conversions to HRESULT

NTSTATUS ntstatus = STATUS_SUCCESS;
HRESULT hr = HRESULT_FROM_NT(ntstatus);

DWORD winerror = ERROR_SUCCESS;
HRESULT hr = HRESULT_FROM_WIN32(winerror);

Conversions from HRESULT

HRESULT = S_OK;
NTSTATUS ntstatus = STATUS_SUCCESS;
if (hr & FACILITY_NT_BIT)
{
  ntstatus = hr & ~FACILITY_NT_BIT;
} else if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
{
  ntstatus = NTSTATUS_FROM_WIN32(HRESULT_CODE(hr));
} else if (SUCCEEDED(hr))
{
  ntstatus = STATUS_SUCCESS;
} else
{
  ntstatus = STATUS_UNSUCCESSFUL;
}

HRESULT hr = S_OK;
DWORD winerror = ERROR_SUCCESS;
if (SUCCEEDED(hr))
{
  winerror = S_OK;
} else if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
{
  winerror = HRESULT_CODE(hr);
} else
{
  winerror = ERROR_UNIDENTIFIED_ERROR;
}

Tuesday, September 13, 2011

WINERROR

WINERROR has it's roots in DOS which is why it is also referred to as DosError. RtlNtStatusToDosError() is an example which will be discussed more later. DOS errors were in turn derived from the C standard library errno.

Values of WINERROR are defined in winerror.h and look like ERROR_SUCCESS. They are an enumeration that are expected to fit in the lower 16bits of the 32bit WINERROR type, more on that later. WINERROR values are sometimes returned through the API result, but often an API will return a BOOL or HANDLE and pass any errors to SetLastError() and then return FALSE or an invalid-handle, the caller will retrieve the WINERROR by calling GetLastError(). ERROR_SUCCESS is the only success value for WINERROR.

Api Examples:

DWORD ApiReturningWinerror(HANDLE handle)
{
  if (handle == INVALID_HANDLE_VALUE) {
    return ERROR_INVALID_PARAMETER;
  }
  return ERROR_SUCCESS;
}

DWORD winerror = ERROR_SUCCESS;
HANDLE handle = INVALID_HANDLE_VALUE;
winerror = ApiReturningWinerror(handle);
if (winerror != ERROR_SUCCESS)
{
  printf("ApiReturningWinerror returned %d", winerror);
  exit();
}

BOOL ApiReturningBool(HANDLE handle)
{
  if (handle == INVALID_HANDLE_VALUE) {
    SetLastError(ERROR_INVALID_PARAMETER);
    // The caller should call GetLastError()
    return FALSE;
  }
  // the common pattern is that SetLastError
  // is only called on failure.
  // Thus the caller should NOT call GetLastError()
  return TRUE;
}

DWORD winerror = ERROR_SUCCESS;
HANDLE handle = INVALID_HANDLE_VALUE;
if (!ApiReturningBool(handle))
{
  winerror = GetLastError();
  printf("ApiReturningBool returned %d", winerror);
  exit();
}

Conversions to WINERROR

NTSTATUS ntstatus = STATUS_SUCCESS;
DWORD winerror = RtlNtStatusToDosError(ntstatus);
if (winerror == ERROR_MR_MID_NOT_FOUND)
{
  // there is no conversion
  return ERROR_UNIDENTIFIED_ERROR;
#if 0
  // The following is common, but doesn't work out well
  // especially when combined with HRESULT_FROM_WIN32
  // and NTSTATUS_FROM_WIN32
  return ntstatus;
#endif
}

HRESULT hr = S_OK;
DWORD winerror = ERROR_SUCCESS;
if (SUCCEEDED(hr))
{
  winerror = S_OK;
} else if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
{
  winerror = HRESULT_SCODE(hr);
} else
{
  winerror = ERROR_UNIDENTIFIED_ERROR;
}

Conversions from WINERROR

DWORD winerror = ERROR_SUCCESS;
HRESULT hr = HRESULT_FROM_WIN32(winerror);

DWORD winerror = ERROR_SUCCESS;
NTSTATUS ntstatus = NTSTATUS_FROM_WIN32(winerror);

Both of the FROM_WIN32 macros work by masking only the lower 16bits of the WINERROR value into the resulting NTSTATUS or HRESULT

Thursday, September 8, 2011

error codes in Windows

Differences between and best practices for WINERROR, HRESULT, RPC_STATUS, SECURITY_STATUS and NTSTATUS?

Why would a developer care?

These error types and their values are an often ignored part of the API contract. Using the return value incorrectly has the same type of consequences as using a cast to pass the wrong data type to a parameter of an API, code just doesn't work, and often fails first in the wild.

I recently began running into code like this:

// ERROR_SUCCESS is a WINERROR value
NTSTATUS status = ERROR_SUCCESS;
WCHAR* buffy;

buffy = (WCHAR*)malloc(1);
if (buffy == NULL)
{
  // this is an HRESULT value
  status = E_OUTOFMEMORY;
}

// not only is this a WINERROR value, but HRESULT and
// NTSTATUS have many success values, not just one
if (status != ERROR_SUCCESS)
{
  return status;
}

I went searching for information about what each type is and the relationships between them and how to use them correctly. Here is what I learned.

They are all 32bit values, some signed some unsigned. Some are defined in terms of bit fields and require macros or inline-functions to check their current state. Others are straight enumerations.

One of the complexities is best demonstrated with the HRESULT type. Lets look at the out of memory condition. Here are some of the possible encodings:

ExpressionHRESULT value
E_OUTOFMEMORY0x8007000E
HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY)0x8007000E
HRESULT_FROM_NT(STATUS_NO_MEMORY)0xD0000017
HRESULT_FROM_NT(
NTSTATUS_FROM_WIN32(ERROR_OUTOFMEMORY))
0xD007000E
STG_E_INSUFFICIENTMEMORY0x80030008
NTE_NO_MEMORY0x8009000E

There was some effort to make the values agree across the different expressions.

Many Api's will pick a set of return codes and then build internal maps from all the errors they receive from other Api's to the set they have decided to return. Thus most code calling Api's can expect that only one encoding will be returned.

Primary Windows Error Types

There will be subsequent posts that expand on each of these types. Here is a summary:

WINERROR

Includewinerror.h
TypeDWORD
Structurevalues in the range 0-16384
Successvalue == ERROR_SUCCESS
Failurevalue != ERROR_SUCCESS
ConversionsHRESULT_FROM_WIN32(value)
NTSTATUS_FROM_WIN32(value)

HRESULT

Includewinerror.h
TypeHRESULT
Structure[1bit Severity]
[1bit Reserved]
[1bit Customer]
[1bit FACILITY_NT_BIT]
[12bit Facility]
[16bit Code]
SuccessSUCCEEDED(value)
FailureFAILED(value)
ConversionsHRESULT is a superset
of all the other error types.
They all have lossless conversions
to HRESULT but it doesn't have
lossless conversions to anything else

NTSTATUS

Include
#define WIN32_NO_STATUS
#include <windows.h>
#undef WIN32_NO_STATUS

#include <winternl.h>
#include <ntstatus.h>
TypeNTSTATUS
Structure[2bit Severity]
[1bit Customer]
[1bit Reserved]
[12bit Facility]
[16bit Code]
SuccessNT_SUCCESS(value)
Failure!NT_SUCCESS(value)
Other
Tests
NT_INFORMATIONAL(value)
NT_WARNING(value)
NT_ERROR(value)
ConversionsHRESULT_FROM_NT(value)

Derived/Subset Windows Error Types

RPC_STATUS

Includerpcnterr.h
TypeRPC_STATUS
StructureA subset of the WINERROR values, redefined as RPC_S_...
Successvalue == RPC_S_OK
Failurevalue != RPC_S_OK
ConversionsHRESULT_FROM_WIN32(value)
NTSTATUS_FROM_WIN32(value)

SECURITY_STATUS

Includewinerror.h
TypeSECURITY_STATUS or HRESULT
StructureA subset of the HRESULT values (from FACILITY_NULL and FACILITY_SECURITY)
SuccessSUCCEEDED(value)
FailureFAILED(value)
Conversions

Tuesday, September 6, 2011

hello

Welcome to my unconsciously fictional autobiography

I expect that most of what I write here will be about things I have already experienced and therefore from my unique memory of them.

A radiolab podcast about Memory and Forgetting described how every time we recall a memory it is rewritten and that each time it is rewritten it is slightly modified. So that each time we remember something the memory becomes less accurate.

Maybe some of my fiction will be incorporated into the fiction of the reader, which is ultimately the point of this.

Thank you