Search code examples
c++windows-runtimec++-winrt

C++/WinRT - process exited with code -1073741819


I am using C++/WinRT to access the HumanInterfaceDevices API from Microsoft. I get

process exited with code -1073741819

when trying to call the GetDeviceSelector API. The program terminates for some reason, but I'm unable to understand why.

What's the issue with the following code and how do I fix it?

#include "pch.h"
#include <iostream>
#include <string>

using namespace winrt;
using namespace Windows::Foundation;
using namespace winrt::Windows::Devices::HumanInterfaceDevice;

int main()
{
    //uint16_t const pid[] = { 0xBA0, 0x5C4, 0x09CC }
   
    init_apartment();
  
    int const product = 0x09CC;
    int const vid = 0x054C;
    int const usagePage = 0x01;
    int const usageId = 0x02;

    IHidDeviceStatics hello;
  
    try {
        printf("trying");
        winrt::hstring data = hello.GetDeviceSelector(usagePage, usageId, vid, product);
    }
    catch (...) {
        printf("error\n");
     
    } 
}


Solution

  • When you execute the code under a debugger you'll get an exception message in the debug output window along the lines of:

    Exception thrown at <some address> in <program>.exe: 0xC0000005: Access violation reading location 0x0000000000000000.

    when evaluating the following expression:

    hello.GetDeviceSelector(usagePage, usageId, vid, product)
    

    The code is trying to read from address zero. That address isn't mapped into any process, raising an Access Violation (SEH) exception with error code 0xC0000005 (that's the hexadecimal representation of -1073741819; use the MagNumDB if you need quick help with any numeric error code on Windows).

    hello here is a default-constructed IHidDeviceStatics object, a C++/WinRT smart pointer type holding a nullptr. Dereferencing it will consequently trigger the Access Violation exception.

    That said, you rarely ever need to interact with IXyzStatics interfaces; C++/WinRT deals with that for you already, and instead provides static class members on the corresponding projected Windows Runtime type (HidDevice)1.

    The fix is simple:

    winrt::hstring data = HidDevice::GetDeviceSelector(usagePage, usageId, vid, product);
    std::wcout << data.c_str() << std::endl;
    

    produces the following output:

    System.Devices.InterfaceClassGuid:="{4D1E55B2-F16F-11CF-88CB-001111000030}" AND System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#True AND System.DeviceInterface.Hid.UsagePage:=1 AND System.DeviceInterface.Hid.UsageId:=2 AND System.DeviceInterface.Hid.VendorId:=1356 AND System.DeviceInterface.Hid.ProductId:=2508


    1 This is somewhat involved. Raymond Chen covered this in On static methods in the Windows Runtime and C++/WinRT.