winapinotificationswindows-10integration

Is there a way to detect changes in Focus Assist (formerly Quiet Hours) in Windows 10 from a Win32 App


I'd like to change the presence state in an App automatically to DND when Focus Assist is turned on.

So two questions basically:


Solution

  • As far as I know there is no officially documented way of getting the Focus assist status.

    It still can be accessed by querying the WNF State of the feature, although this is completely undocumented and not officially supported.

    The various states for WNF Data have been reverse engineered, so the one for Focus Assist is WNF_SHEL_QUIETHOURS_ACTIVE_PROFILE_CHANGED.

    The C++ sample below shows how to get the state of Focus Assist feature (mostly off, priority_only and alarm_only).

    Once again, be wary that this is not officially supported by Microsoft:

    #include <Windows.h>
    #include <iostream>
    #include <string>
    #include <map>
    
    // from ntdef.h
    #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
    
    // from ntdef.h
    typedef struct _WNF_STATE_NAME
    {
        ULONG Data[2];
    } WNF_STATE_NAME;
    
    typedef struct _WNF_STATE_NAME* PWNF_STATE_NAME;
    typedef const struct _WNF_STATE_NAME* PCWNF_STATE_NAME;
    
    typedef struct _WNF_TYPE_ID
    {
        GUID TypeId;
    } WNF_TYPE_ID, *PWNF_TYPE_ID;
    
    typedef const WNF_TYPE_ID* PCWNF_TYPE_ID;
    
    typedef ULONG WNF_CHANGE_STAMP, *PWNF_CHANGE_STAMP;
    
    
    enum FocusAssistResult
    {
        not_supported = -2,
        failed = -1,
        off = 0,
        priority_only = 1,
        alarms_only = 2
    };
    
    std::map<int, std::string> result_map = {
        {-2, "Not Supported"},
        {-1, "Failed"},
        {0, "Off"},
        {1, "Priority Only"},
        {2, "Alarm Only"}
    };
    
    typedef NTSTATUS (NTAPI *PNTQUERYWNFSTATEDATA)(
        _In_ PWNF_STATE_NAME StateName,
        _In_opt_ PWNF_TYPE_ID TypeId,
        _In_opt_ const VOID* ExplicitScope,
        _Out_ PWNF_CHANGE_STAMP ChangeStamp,
        _Out_writes_bytes_to_opt_(*BufferSize, *BufferSize) PVOID Buffer,
        _Inout_ PULONG BufferSize);
    
    int main(int argc, CHAR** argv)
    {
        // note: ntdll is guaranteed to be in the process address space.
        const auto h_ntdll = GetModuleHandle(_T("ntdll"));
    
        // get pointer to function
        const auto pNtQueryWnfStateData = PNTQUERYWNFSTATEDATA(GetProcAddress(h_ntdll, "NtQueryWnfStateData"));
        if (!pNtQueryWnfStateData)
        {
            std::cerr << "[-] Error: couldn't get pointer to NtQueryWnfStateData() function." << std::endl;
            return -1;
        }
    
        // state name for active hours (Focus Assist)
        WNF_STATE_NAME WNF_SHEL_QUIETHOURS_ACTIVE_PROFILE_CHANGED{0xA3BF1C75, 0xD83063E};
    
        // note: we won't use it but it's required
        WNF_CHANGE_STAMP change_stamp = {0};
    
        // on output buffer will tell us the status of Focus Assist
        DWORD buffer = 0;
        ULONG buffer_size = sizeof(buffer);
    
        if (NT_SUCCESS(pNtQueryWnfStateData(&WNF_SHEL_QUIETHOURS_ACTIVE_PROFILE_CHANGED, nullptr, nullptr, &change_stamp, 
            &buffer, &buffer_size)))
        {
            // check if the result is one of FocusAssistResult
            if (result_map.count(buffer) == 0)
            {
                std::cout << "Focus Assist result is unknown." << std::endl;
            }
            else
            {
                std::cout << "Focus assist state: " << result_map[buffer] << std::endl;
            }
        }
        else
        {
            std::cerr << "[-] Error while calling NtQueryWnfStateData." << std::endl;
            return -1;
        }
    
        return 0;
    }