Friday, September 6, 2013

RxC++ ReactiveCommand

I rewrote the ReactiveCommand class (from Paul Betts ReactiveUI library for C#) to demonstrate how to bind async commands to Xaml Buttons. This is a work in progress (it does not use data binding yet, is missing some error handling and there is no reason that it should be specific to the Xaml UI framework - should work with WIN32 button etc..), but I did build it for use in this Windows 8.1 sample.

ReactiveCommand models calls to the Execute function as a Sequence of the value passed to each Execute. All subscriptions to it are called on the UI thread. There can be many subscriptions directly to ReactiveCommand, there can also be many async functions registered.

Each async function registered takes the value passed to Execute does work and returns a result. Each call to RegisterAsyncCommand returns a new Sequence of the results from each call to the registered function. All subscriptions to the Sequence of results are called on the UI thread.

ReactiveCommand also provides Sequences of bools, that can be subscribed, that represent its state. When the CanExecute Sequence is bound to the enabled property of the button the state of the ReactiveCommand is communicated into the ui.

By default ReactiveCommand will ignore Execute until all the subscribers (sync and async) to the previous Execute call have finished. This can be changed during construction.

Here is some (out-of-order) usage from the sample.

Subscription - async version (Scenario1.Xaml.cpp):

Subscription - sync version (Scenario1.Xaml.cpp):

Binding (Scenario1.Xaml.cpp):

Creation (Scenario1.Xaml.cpp):

Create state sequences that are used by these ReactiveCommand (Scenario1.Xaml.cpp):

Thursday, September 5, 2013

DeferOperation

I have been working on RxC++ for a few months now. I have added Schedulers and lots of operators. Now I am trying to apply Rx to a C++ Windows Store app.

I was told that Deferrals did not compose well with Rx. This motivated me to design the DeferOperation operator.

DeferOperation demonstrates how Rx can be extended by a few engineers to provide services for many. Another way to say this is that Rx allows Async Algorithms to be written once, carefully, so that many others can re-use them.


These are all references to the Windows 8.1 Accelerometer sample I am modifying.

Usage (App.Xaml.Cpp):

DeferOperation defaults to the ui thread by reading the context off of the Window, but when the suspending event is fired the Window is not valid, so this uses the current thread scheduler explicitly. publish and connect_forever ensure that the work is done even if nothing subscribes the result.


The implementation follows.

The core of the DeferOperation operator is (cpprx/rx-winrt.hpp):

sop is the first lambda from the usage (cpprx/rx-winrt.hpp):

sob is the second lambda from the usage (the OperationPattern is passed so that the SuspendingOperation and the Deferral are available to the sequence if it wants to see the Deadline or Complete early, for example) (cpprx/rx-winrt.hpp)
Using will retrieve the resource (OperationPattern), subscribe to the result of sob and Dispose the resource when the subscription completes or errors.

OperationPattern provides the abstraction needed by Using. It will call get and complete the deferral (cpprx/rx-winrt.hpp):
 

Friday, August 30, 2013

Reactive Extensions for C++

I get excited when I can compose asynchronous code without using thread or lock API's

A C++/CX Windows 8.1 sample app that demonstrates using the accelerometer.

Now see it transformed using Rx++
https://github.com/kirkshoop/rxaccelerometer

Examples 

Create a ReactiveCommand and bind it to a Xaml button


Transform SaveAsync method to ReactiveSave

Introduction to Rx
Reactive Extensions Rx were born as a transformation of LINQ expressions which pull from a data source through a set of operators into an Rx expression where the data source pushes through a set of operators.

Personally, I recognized them as the generalization I wanted to make of a pattern I had popularized in a previous project. We called them Sender/Receiver, Rx calls them Observable/Observer

Observable and Observer
An Observable is a source of data. An Observer operates on data as the source provides it. An Observer connects to an Observable by Subscribing to it. Many Observers can connect to the same Observable. 

A Subject is both an Observable and an Observer and will pass the data sent to the Observable on to each of the Observers that are Subscribed to the Observable.

An Operator is a function that takes at least one Observable argument and returns a new Observable.

Web Resources
There is a lot of information about Rx. Most of the information is focused on the .Net version as that came first. More recently there have been other versions built.

A partial list of Rx implementations:
Aaron Lahmann, a friend (and one-time co-worker in the team where I was working on Sender/Receiver) wrote Rx++ and was talking to me about it at the time. I still did not know enough about it to jump on it at the time.


Eventually, I saw an article by Jafar Husain that linked to an RxJS tutorial that got me excited. I highly recommend taking the time to follow through the examples.


Saturday, May 12, 2012

ZeroMQ and C++ without exceptions

my comment in reply to martin_sustrik.

I wanted to post some code into the comment but I finally gave up. I will post it here instead. Disclaimer: this code has not been compiled.

class foo
{
public:
  ~foo() {}
  foo(foo&& other) {
    guts.a = std::move(other.a); // no-fail
  }
  foo& operator=(foo other) { // no-fail
    using std::swap; 
    swap(guts.a, other.guts.a); 
    return *this;
  } 
  static optional<foo> init() {
    optional<foo> result; 
    type guts = {}; // ~type() cleans up on exit
    guts.a.reset(new(std::nothrow) int(5));
    if (!guts.a) {return result;} // no foo constructed 
    result.reset(foo(guts)); //no-fail move construction
    return std::move(result); // no-fail move of result
  }
  int do() {return guts.a.get();} // a cannot be empty
private:
  struct type { std::unique_ptr<int> a; };
  type guts;
  foo(); // disabled
  foo(const foo&); // disabled
  foo(type&& gutsArg) {guts.a = std::move(gutsArg.a);} // no-fail
};

auto MyFoo = foo::init();
if (!MyFoo) return;
MyFoo->do();

if you want to return a detailed error from init() change init() to return a tuple:

  static std::tuple<error, optional<foo>> init();
and use tie to break the result into local vars:
  optional<foo> MyFoo;
  error MyError;
  std::tie(MyError, MyFoo) = foo::init();

Tuesday, April 17, 2012

console app that monitors smart cards

Here is a console app that demonstrates how to tie the smart card functions already covered into a working monitor that prints reader state changes and the certs and subject names for the cards that are present.

#pragma once

// Exclude rarely-used stuff from
// Windows headers
#define WIN32_LEAN_AND_MEAN
// skip min/max macros from
// Windows Headers
#define NOMINMAX
// Windows Header Files:
#include <windows.h>
#include <Unknwn.h>
#include <winscard.h>
#include <ncrypt.h>
#include <Wincrypt.h>
#include <credentialprovider.h>

// C++ library header files:
#include <type_traits>
#include <algorithm>
#include <new>
#include <memory>
#include <utility>
#include <limits>
#include <iterator>
#include <thread>
#include <future>
#include <mutex>
#include <vector>
#include <iostream>
#include <iomanip>

// local header files:
#define LIBRARIES_NAMESPACE nslib
#include <libraries.h>
namespace lib = LIBRARIES_NAMESPACE;

#include "..\win32project1\scard_monitor.h"

Set a breakpoint in each of these functions and see where error codes first make an appearance in this module. the static anchor is a device to make sure that the compiler does not eliminate or fold them together.

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

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

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

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

Helper functions to print status and certificate properties.

template<typename Certificate>
void printCertificates(
  lib::rng::range<Certificate> certificates)
{
  for (auto & key : certificates) {
    unique_winerror winerror;

    PCCERT_CONTEXT certcontext = (
      CertCreateCertificateContext(
        X509_ASN_ENCODING | 
          PKCS_7_ASN_ENCODING,
        &key.cert[0],
        key.cert.size()
      )
    );
    winerror = make_winerror_if(!certcontext);

    if (!winerror) {
      std::wcout 
        << L"could not get cert context" 
        << std::endl;
      continue;
    }

    DWORD sizesubject = 0;
    std::wstring subjectname;
    for (bool getsize = true; ; getsize = false) {
      sizesubject = CertGetNameString(
        certcontext,
        CERT_NAME_FRIENDLY_DISPLAY_TYPE,
        0,
        NULL,
        getsize ? nullptr : &subjectname[0],
        sizesubject
      );
      if (sizesubject == 1) {
        std::wcout 
          << L"could not get subject name" 
          << std::endl;
        break;
      }
      if (getsize) {
        subjectname.resize(sizesubject - 1);
      } else {
        std::wcout 
          << L"key name: " << key.key.c_str() 
          << L" subject name: " << subjectname.c_str() 
          << std::endl;
        break;
      }
    }
  }
}

template<typename Stream>
Stream& printSCardState(Stream& stream, DWORD state)
{
  stream
    << ((state == SCARD_STATE_UNAWARE)  ? 
      L" SCARD_STATE_UNAWARE" : L"")
    << ((state & SCARD_STATE_PRESENT)  ? 
      L" SCARD_STATE_PRESENT" : L"")
    << ((state & SCARD_STATE_ATRMATCH)  ? 
      L" SCARD_STATE_ATRMATCH" : L"")
    << ((state & SCARD_STATE_CHANGED)  ? 
      L" SCARD_STATE_CHANGED" : L"")
    << ((state & SCARD_STATE_EMPTY)  ? 
      L" SCARD_STATE_EMPTY" : L"")
    << ((state & SCARD_STATE_EXCLUSIVE)  ? 
      L" SCARD_STATE_EXCLUSIVE" : L"")
    << ((state & SCARD_STATE_IGNORE)  ? 
      L" SCARD_STATE_IGNORE" : L"")
    << ((state & SCARD_STATE_INUSE)  ? 
      L" SCARD_STATE_INUSE" : L"")
    << ((state & SCARD_STATE_MUTE)  ? 
      L" SCARD_STATE_MUTE" : L"")
    << ((state & SCARD_STATE_UNAVAILABLE)  ? 
      L" SCARD_STATE_UNAVAILABLE" : L"")
    << ((state & SCARD_STATE_UNKNOWN)  ? 
      L" SCARD_STATE_UNKNOWN" : L"")
    << ((state & SCARD_STATE_UNPOWERED)  ? 
      L" SCARD_STATE_UNPOWERED" : L"")
  ;
  return stream;
}

int wmain(int argc, WCHAR* argv[])
{
  unique_winerror winerror;
  for (;;) {
    SCARDCONTEXT context = NULL;

    HANDLE waitfor[] = {SCardAccessStartedEvent()};
    ON_UNWIND_AUTO([] {SCardReleaseStartedEvent();});

    winerror = smart_card::monitor_smartcard_readers(
      [&](SCARDCONTEXT context) {
        context = context;
      },
      [&]() {
        context = NULL;
      },
      [&]() -> bool {
        if (WAIT_OBJECT_0 != WaitForMultipleObjects(
          lib::rng::size(waitfor), 
          waitfor, 
          FALSE, 
          INFINITE)
        ) {
          // monitor_smardcard_readers will return 
          // SCARD_E_CANCELLED
          return false;
        }
        return true;
      },
      [&](
        lib::rng::range<SCARD_READERSTATE*> readersrange
      ) {
        for (auto & state : readersrange) {
          auto stateChanges = (
            (state.dwCurrentState ^ state.dwEventState) & 
              std::numeric_limits<unsigned short>::max()
          );
          std::wcout
            << L"nothread - "
            << state.szReader
            << L" changes: " 
            << std::hex 
            << std::showbase 
            << stateChanges
            << L"["
          ;
          printSCardState(std::wcout, stateChanges)
            << L"] state: " 
            << std::hex 
            << std::showbase 
            << state.dwEventState
            << L"["
          ;
          printSCardState(std::wcout, state.dwEventState)
            << L"]"
            << std::endl
          ;

          if (
            state.dwCurrentState != 
              SCARD_STATE_UNAWARE &&
            ((state.dwEventState & 
              SCARD_STATE_PRESENT) != 
                SCARD_STATE_PRESENT ||
              stateChanges == SCARD_STATE_INUSE ||
              stateChanges == SCARD_STATE_UNPOWERED ||
              (state.dwEventState & (
                SCARD_STATE_UNPOWERED | 
                SCARD_STATE_EMPTY | 
                SCARD_STATE_IGNORE | 
                SCARD_STATE_UNKNOWN | 
                SCARD_STATE_UNAVAILABLE | 
                SCARD_STATE_MUTE)) ||
            state.cbAtr == 0)
          ) {
            // we have seen this reader before 
            // and one of:
            // no card
            // only flipped INUSE
            // only flipped UNPOWERED
            // UNPOWERED EMPTY UNKNOWN UNAVAILABLE MUTE
            // no atr
            //
            // don't try to read the card
            continue;
          }

          CardWithProvider card;
          std::tie(winerror, card) = 
            smart_card::smartcard_name_and_provider(
              lib::rng::make_range_raw(state.rgbAtr)
          );
          if (!winerror) {
            continue;
          }

          KeyWithCertificateVector certificates;
          std::tie(winerror, certificates) = 
            smart_card::smartcard_certificates(
              card.kspname);
          if (!winerror) {
            continue;
          }

          std::wcout << L"nothread -"
          << L" kspname: " << card.kspname.c_str()
          << std::endl;

          printCertificates(
            lib::rng::make_range_raw(certificates)
          );
        }
      }
    );
    winerror.suppress();
  }

  return 0;
}

Thursday, April 12, 2012

smartcard_certificates implementation

Given a provider name NCryptEnumKeys can be used to retrieve all the keys known to that provider. Since the KSP provider is shared across all cards associated to it, the keys from all associated cards will be returned.

Here is a function that uses NCryptEnumKeys and NCryptGetProperty to retrieve the keys and certificates from a KSP provider name.

struct KeyWithCertificate {
  std::wstring key;
  std::vector<BYTE> cert;
};
typedef
  std::vector<KeyWithCertificate>
KeyWithCertificateVector;

inline
std::pair<unique_winerror, KeyWithCertificateVector>
smartcard_certificates(
  const std::wstring& kspstring
)
{
  unique_winerror winerror;
  KeyWithCertificateVector output;

  NCRYPT_PROV_HANDLE provider = NULL;
  ON_UNWIND_AUTO(
    [&] { 
      if (provider) {
        NCryptFreeObject(provider);
      }
    }
  );
  winerror.reset(
    NCryptOpenStorageProvider(
        &provider,
        kspstring.c_str(),
        0
    )
  );
  if (!winerror) {
    return std::make_pair(winerror, std::move(output));
  }

  NCryptKeyName* keyname = nullptr;
  ON_UNWIND_AUTO(
    [&] { 
      if (keyname) {
        NCryptFreeBuffer(keyname);
      }
    }
  );
  void* enumstate = nullptr;
  ON_UNWIND_AUTO(
    [&] { 
      if (enumstate) {
        NCryptFreeBuffer(enumstate);
      }
    }
  );
  for (;;) {
    winerror.reset(
      NCryptEnumKeys(
          provider,
          NULL,
          &keyname,
          &enumstate,
          NCRYPT_SILENT_FLAG
      )
    );
    if (winerror == winerror_cast(NTE_NO_MORE_ITEMS)) {
      winerror.suppress().release();
      break;
    }
    if (!winerror) {
      return std::make_pair(winerror, std::move(output));
    }

    KeyWithCertificate keystate;
    keystate.key = keyname->pszName;

    NCRYPT_KEY_HANDLE key = NULL;
    ON_UNWIND_AUTO(
      [&] { 
        if (key) {
          NCryptFreeObject(key);
        }
      }
    );
    winerror.reset(
      NCryptOpenKey(
          provider,
          &key,
          keyname->pszName,
          keyname->dwLegacyKeySpec,
          NCRYPT_SILENT_FLAG
      )
    );
    if (!winerror) {
      return std::make_pair(winerror, std::move(output));
    }

    DWORD sizecert = 0;
    for (bool getsize = true; ; getsize = false) {
      winerror.reset(
        NCryptGetProperty(
            key,
            NCRYPT_CERTIFICATE_PROPERTY,
            getsize ? nullptr : &keystate.cert[0],
            sizecert,
            &sizecert,
            0
        )
      );
      if (!winerror) {
        return std::make_pair(winerror, std::move(output));
      }
      if (getsize) {
        keystate.cert.resize(sizecert);
      } else {
        break;
      }
    }

    output.push_back(keystate);
  }

  return std::make_pair(winerror, std::move(output));
}

Tuesday, April 10, 2012

smartcard_name_and_provider implementation

Once the reader monitor has reported the ATR for the card in a reader, it can be used to access the card.

Windows has a model that gives card manufacturers three options for providing access to a smart card through the crypto apis.

  • KSP/CSP - the manufacturer can supply a full KSP(Key Storage Provider) and CSP (Cryptographic Service Provider) and associate it with an ATR.
  • Smart Card Minidriver - the manufacturer can supply a minidriver dll that the built-in Smart Card KSP and CSP will load to provide access and associate it with an ATR.
  • PICS/GIDS - the manufacturer can provide a card that implements the GIDS or PICS card standard. Windows has built-in minidrivers for these.

Because of the first option, once an ATR is in hand, SCardGetCardTypeProviderName must be called to retrieve the KSP or CSP provider name that should be used for the card.

SCardListCards will retrieve the card name from an ATR, which is then passed to SCardGetCardTypeProviderName. Windows only supports one KSP/CSP for an ATR, so even though SCardListCards returns a list of card names any one of them can be used to retrieve the provider names.

Here is the code to get a card name and the KSP provider name.

struct CardWithProvider {
  std::wstring cardname;
  std::wstring kspname;
};

inline
std::pair<unique_winerror, CardWithProvider>
smartcard_name_and_provider(
  lib::rng::range<const BYTE*> atr
)
{
  unique_winerror winerror;
  unique_close_scardcontext context;

  CardWithProvider output;

  winerror.reset(
    SCardEstablishContext(
        SCARD_SCOPE_USER,
        NULL,
        NULL,
        context.replace()
    )
  );
  if (!winerror) {
    return std::make_pair(winerror, std::move(output));
  }

  LPWSTR kspstring = nullptr;
  ON_UNWIND(
    unwind_kspstring,
    [&] { 
      if (kspstring) {
        SCardFreeMemory(context.get(), kspstring);
      }
    }
  );
  DWORD ksplength = SCARD_AUTOALLOCATE;

  LPWSTR cardsstring = nullptr;
  ON_UNWIND_AUTO(
    [&] { 
      if (cardsstring) {
        SCardFreeMemory(context.get(), cardsstring);
      }
    }
  );
  DWORD cardslength = SCARD_AUTOALLOCATE;

  winerror.reset(
    SCardListCards(
        context.get(),
        atr.begin(),
        NULL,
        NULL,
        reinterpret_cast<LPWSTR>(&cardsstring),
        &cardslength
    )
  );
  if (winerror == 
      winerror_cast(SCARD_E_READER_UNAVAILABLE)) {
    winerror.suppress();
    // don't free the static string we are 
    // about to assign
    unwind_kspstring.dismiss();
    kspstring = MS_SMART_CARD_KEY_STORAGE_PROVIDER;
    ksplength = wcslen(kspstring);
  } else if (!winerror) {
    return std::make_pair(winerror, std::move(output));
  } else {
    winerror.reset(
      SCardGetCardTypeProviderName(
          context.get(),
          cardsstring,
          SCARD_PROVIDER_KSP,
          reinterpret_cast<LPWSTR>(&kspstring),
          &ksplength
      )
    );
    if (!winerror) {
      return std::make_pair(winerror, std::move(output));
    }
  }

  if (cardsstring) {
    output.cardname = cardsstring;
  }
  output.kspname = kspstring;

  return std::make_pair(winerror, std::move(output));
}

Thursday, April 5, 2012

monitor_smartcard_readers implementation

The Win32 API to monitor smart card readers is SCardGetStatusChange. However its usage is sufficiently complex and arcane that a post like this is warranted to show usage.

SCardGetStatusChange blocks until a change takes place at which point it returns. An array containing state for each reader is passed in to indicate the state as understood by the caller and when the function detects a difference between the actual state and the state in the array the function updates the array with the new state and returns. The caller then processes the changes and then calls back with its new understanding.

template<
  typename SetContext, 
  typename ClearContext,
  typename Wait,
  typename Report
>
unique_winerror monitor_smartcard_readers(
  SetContext && setContext,
  ClearContext && clearContext,
  Wait && wait,
  Report &&  report
)
{
  unique_winerror winerror;

These hold the output of SCardListReaders and the input/output for SCardGetStatusChange. In fact the readers elements contain pointers into the readernames array. This is why readernames is first so that its lifetime exceeds the lifetime of readers. There is additional code to maintain this lifetime contract further down.

  std::vector<wchar_t> readernames;
  std::vector<SCARD_READERSTATE> readers;

  while (winerror) {

make sure that the smart card service has started and that the loop has not been cancelled


    if (!std::forward<Wait>(wait)()) {
      return winerror_cast(SCARD_E_CANCELLED);
    }

    monitor_error_contract(
    [&]() {

      unique_close_scardcontext context;
      ON_UNWIND_AUTO(
        [&] {
          std::forward<ClearContext>(clearContext)();
        }
      );

need a fresh context whenever we start over. lots of system changes could have caused this restart including the smart card service stopping.


      winerror.reset(
        SCardEstablishContext(
            SCARD_SCOPE_USER,
            NULL,
            NULL,
            context.replace()
        )
      );
      if (!winerror || !context) {
        return;
      }

      std::forward<SetContext>(setContext)(context.get());

make sure that the loop has not been cancelled. without this second wait there is a race where the new context is not cancelled because the caller cancelled the context at a time when there was no context.


      if (!std::forward<Wait>(wait)()) {
        winerror = winerror_cast(SCARD_E_CANCELLED);
        return;
      }

      if (readers.empty()) {

Windows allows smart card readers to be inserted and removed from the machine. In order to support these Plug-and-Play events a static reader name was defined so that SCardGetStatusChange can report PnP changes. the make function defaults the initial state to unaware which causes SCardGetStatusChange to return immediately with the actual PnP state.

        readers.push_back(
          make(L"\\\\?PnP?\\Notification")
        );
      }

      for (;;) {
        auto readersstaterange = lib::rng::make_range_raw(
          readers
        );

        winerror.reset(
          SCardGetStatusChange(
              context.get(),
              INFINITE,
              readersstaterange.begin(),
              lib::rng::size_cast<DWORD>(
                readersstaterange.size()
              )
          )
        );
        if (!winerror) {
          // exit
          return;
        }

report the smart card reader state

        auto readersrange = lib::rng::make_range_raw(
          readers, 
          0, 
          -1
        );
        if (!readersrange.empty()) {
          std::forward<Report>(report)(readersrange);
        }

record the changes now that they have been reported. setting dwCurrentState = dwEventState is required before calling SCardGetStatusChange again or the function will just return immediately to report the same changes.

        for (auto & state : readers) {
          state.dwCurrentState = state.dwEventState;
        }

        if ((
            readers.back().dwEventState & 
            SCARD_STATE_CHANGED
          ) == SCARD_STATE_CHANGED
        ) {
          // Pnp event - list readers.
          break;
        }
      }

A PnP event occured. must keep the existing allocations for use while building the new list.

      std::vector<wchar_t> oldreadernames(
        std::move(readernames)
      );
      std::vector<SCARD_READERSTATE> oldreaders(
        std::move(readers)
      );

create a range of the existing reader states that excludes the static pnp state

      auto oldreaderssortedrange = lib::rng::make_range(
        oldreaders,
        0, 
        -1
      );

      LPWSTR concatreaderstrings = nullptr;
      ON_UNWIND_AUTO(
        [&] { 
        if (concatreaderstrings) {
          SCardFreeMemory(
            context.get(), 
            concatreaderstrings
          );
        };
      }
      );
      DWORD totallength = SCARD_AUTOALLOCATE;

      winerror.reset(
        SCardListReaders(
            context.get(),
            nullptr,
            reinterpret_cast<LPWSTR>(&concatreaderstrings),
            &totallength
        )
      );

no readers is not an error, just loop around to wait for a reader to be connected

      if (winerror == 
          winerror_cast(SCARD_E_NO_READERS_AVAILABLE)
      ) {
        winerror.suppress().release();
        return;
      } else if (!winerror) {
        return;
      }

save a copy of the reader names because the state array will have pointers into them.

      readernames.assign(
        concatreaderstrings, 
        concatreaderstrings + totallength
      );

      auto readerstateless = [](
        const SCARD_READERSTATE & lhs, 
        const SCARD_READERSTATE & rhs
      ) -> bool {
        return _wcsicmp(lhs.szReader, rhs.szReader) < 0;
      };

all the reader names are concatenated in this array with embedded nulls for each and two nulls to mark the end

      auto cursorreadernames = lib::rng::make_range_raw(
        readernames
      );
      while (
        !cursorreadernames.empty() && 
        cursorreadernames.front() != L'\0'
      ) {
        // access the current name
        auto namerange = lib::rng::make_range(
          cursorreadernames,
          0,
          wcslen(
            cursorreadernames.begin()
          ) - cursorreadernames.size()
        );
        // skip to the next name
        cursorreadernames = lib::rng::make_range(
          namerange, 
          namerange.size() + 1, 
          0
        );

find this reader in the old list of readers. This list is kept sorted so that std::equal_range can be used.

        auto oldreader = std::equal_range(
          oldreaderssortedrange.begin(),
          oldreaderssortedrange.end(),
          make(namerange.begin()),
          readerstateless
        );
        if (oldreader.first != oldreader.second) {
          // keep the old state for this reader
          readers.push_back(*oldreader.first);

          // must use the new string allocation,
          // the old one will be gone soon
          readers.back().szReader = namerange.begin();
        } else {
          // this reader has not been seen yet.
          // make defaults to setting the state to 
          // unaware, so that the next call to
          // SCardGetStatusChange will return 
          // immediately with the actual state.
          readers.push_back(make(namerange.begin()));
        }
      }

keeping the reader states sorted makes the updates more stable and allows the std::equal_range above instead of a linear find.

      std::sort(
        readers.begin(), 
        readers.end(), 
        readerstateless
      );

add PnP state query to the new list. keep the existing state, and keep it at the end of the list, out of the sorted area.

      readers.push_back(oldreaders.back());
    }
    );
  }
  return winerror;
}

Tracking the readers state is only the first step. Future posts will explore tracking cards, certificates and subjects/users

Tuesday, April 3, 2012

monitor_smartcard_readers usage

Building a loop to monitor smart cards on windows turns out to be tricky. I have written a function to do this and allow code to be inserted in the necessary places.

template<
  typename SetContext, 
  typename ClearContext,
  typename Wait,
  typename Report
>
unique_winerror monitor_smartcard_readers(
  SetContext && setContext,
  ClearContext && clearContext,
  Wait && wait,
  Report &&  report
);

By itself the data produced by this function isn't too interesting, but I have a project in mind that I hope will use it to advantage.

To use monitor_smartcard_readers you call the function passing in lambdas for the code to insert.

  • setContext when the function establishes a context it calls this lambda to allow the caller to store the context and use it later to call SCardCancel
  • clearContext when the function closes the context it calls this function to inform the caller that it is no longer valid.
  • wait when the function needs to wait for the service to become available or check to see if it should exit it calls this lambda. this lambda must return a bool, true for continue and false for exit.
  • report when the function has an update to the status it calls this lambda with a range of reader states.

A quick example should show how this all stitches together.

void monitor()
{

First need to get the win32 event handle that is set when the smart card service is running.

  HANDLE waitfor[1] = {SCardAccessStartedEvent()};
  ON_UNWIND_AUTO([] {SCardReleaseStartedEvent();});

  unique_winerror winerror;
  SCARDCONTEXT context = NULL;

  while (!winerror) {
    winerror = monitor_smartcard_readers(

when setContext is called, store the context in the local stack variable.

    [&](SCARDCONTEXT context) {
      context = context;
    },

when clearContext is called, set the local stack variable to NULL

    [&]() {
      context = NULL;
    },

when wait is called, wait for the smart card service to start. If additional threads were in play this might include other events to signal that monitor_smartcard_readers should exit.

    [&]() -> bool {
      if (WAIT_OBJECT_0 != WaitForMultipleObjects(
          lib::rng::size(waitfor), 
          waitfor, 
          FALSE, 
          INFINITE
        )
      ) {
        // monitor_smardcard_readers will 
        // return SCARD_E_CANCELLED
        return false;
      }
      return true;
    },

when report is called, print out the state changes.

    [&](
      lib::rng::range<SCARD_READERSTATE*> readersrange
    ) {
      std::wcout << L"---status update---" << std::endl;
      for (auto & state : readersrange) {
        auto stateChanges = (
          state.dwCurrentState ^ state.dwEventState
        ) & std::numeric_limits<unsigned short>::max();
        
        std::wcout << L"reader: " << state.szReader 
        << L" changes: " << 
           std::hex << std::showbase << stateChanges
        << L" state: "
        << ((state.dwEventState == SCARD_STATE_UNAWARE) ? 
           L" SCARD_STATE_UNAWARE" : L"")
        << ((state.dwEventState & SCARD_STATE_PRESENT) ? 
           L" SCARD_STATE_PRESENT" : L"")
        << ((state.dwEventState & SCARD_STATE_ATRMATCH) ? 
           L" SCARD_STATE_ATRMATCH" : L"")
        << ((state.dwEventState & SCARD_STATE_CHANGED) ? 
           L" SCARD_STATE_CHANGED" : L"")
        << ((state.dwEventState & SCARD_STATE_EMPTY) ? 
           L" SCARD_STATE_EMPTY" : L"")
        << ((state.dwEventState & SCARD_STATE_EXCLUSIVE) ? 
           L" SCARD_STATE_EXCLUSIVE" : L"")
        << ((state.dwEventState & SCARD_STATE_IGNORE) ? 
           L" SCARD_STATE_IGNORE" : L"")
        << ((state.dwEventState & SCARD_STATE_INUSE) ? 
           L" SCARD_STATE_INUSE" : L"")
        << ((state.dwEventState & SCARD_STATE_MUTE) ? 
           L" SCARD_STATE_MUTE" : L"")
        << ((state.dwEventState & SCARD_STATE_UNAVAILABLE) ? 
           L" SCARD_STATE_UNAVAILABLE" : L"")
        << ((state.dwEventState & SCARD_STATE_UNKNOWN) ? 
           L" SCARD_STATE_UNKNOWN" : L"")
        << ((state.dwEventState & SCARD_STATE_UNPOWERED) ? 
           L" SCARD_STATE_UNPOWERED" : L"")
        << std::endl; 
      }
      std::wcout << L"--status update end--" << std::endl;
    }
    );
  }
}

Next post will explore the implementation of monitor_smartcard_readers..

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 \
      ); \
    } \
  )