proper requirements to test in house before buying an EV to interact with the secure desktop

David Perry 20 Reputation points
2026-04-21T20:44:22.6533333+00:00

Hey there,

Been in business since 1997, I have approx 2,800 customers I help remotely... currently paying for Anydesk or Teamviewer depending on who is cheaper at the time. To save money, we're programmers as well so we thought we would just make our own... already done an unpolished version that works... BUT... UAC is the problem.

My question is... we are having a problem figuring out how to interact with the secure desktop in a PROPER and Microsoft approved way.

Our program works but naturally, as soon as the UAC prompt is triggered, we can't see what is happening. We manually go over to our test bench, click the UAC prompt, and voila... we can continue remote controlling our test machine and interacting with the elevated cmd prompt or program...

WHAT WE TRIED:

We tried self signed certs for in house testing. Windows says our certs are OK. But, despite making a Remote Control program, a Client and a service running as SYSTEM... we can't figure out how to communicate with the secure desktop. We installed our self signed certs into Root and Trusted in 4 locations. Still won't elevate the token, or talk to the secure desktop.

I assume it's because of the self signed cert...

I do know eventually I will HAVE to buy an EV certificate. That's not a problem when the project is completed for commercial use... but, due to other work commitments it's going to take a while to finish this project so, we want to save as much money as possible in the meantime... EV's in Canada are expensive for a small business. Almost $1k a year.

My question is... will buying the monthly Azure Code Signing cert allow our software written in C# to interact with the secure desktop, elevate tokens, etc...

Also, in case we are doing something wrong... where do we find the information to make these products? Where are all the API calls and ways to accomplish these tasks we are trying to do?

In the old days... lol, I purchased "Mapping the Commodore 64" and it told me everything about the machine. Loved that book. These days we have AI, websites, etc but no real "book" on the OS and how to do things...

I did ask AI and AI kept making up fanciful solutions to the problem. "Oh ya... a self signed cert will 100% work!!!" and then later "it won't work"... so, we asked "would buying an Azure Code Signing cert solve the problem and we get mixed results...

So, as an old school programmer... I am unfamiliar with windows programming... this remote control project is my first decent Windows program anyways. We have dozens more to follow but to save money and time now, we made this one first to save paying Anydesk money every year.

So, any help? What works? What can we use internally FIRST before dropping money on EV's?

Please don't go by what AI says... it makes up stuff... and on this topic, it ignores the Jan - April 2026 hardenings.

Any NON AI programmers out there who can help guide us in the right direction?

Thank you!

David Perry

Perry Computer Services (Canada)

Windows development | Windows API - Win32
0 comments No comments

Answer accepted by question author
RLWA32 52,946 Reputation points
2026-04-23T12:39:29.59+00:00

I did a test on Windows 10 22H2 ESU. Because the secure desktop (Winlogon) has a very restrictive security descriptor only the SYSTEM account has the necessary permissions to manipulate the UAC consent prompt dialog.

A process running in the user's interactive session as SYSTEM received the EVENT_SYSTEM_DESKTOPSWITCH notification that the secure desktop was active (displaying UAC consent prompt). Upon receiving the notication the process starts a new thread that connects to the secure desktop using the Windows API function SetThreadDesktop. The thread initializes COM in the MTA, creates the Automation COM object and uses the Windows API FindWindow function to obtain a handle to the consent prompt dialog. Then it obtained the dialog's IUIAutomationElement and used that to locate and invoke IUIAutomationElement of the "Yes" button to allow the elevation request. The test did not use keystrokes.

Following is the thread procedure that does the work -

DWORD __stdcall UIAConsentProc(PVOID pv)  // Handle to Winlogon Desktop obtained from Winevent handler
{
    CCoInitialize init(COINIT_MULTITHREADED);
    HRESULT hr{ E_FAIL };

    HDESK hDesk = *((HDESK*)pv);

    if (!SetThreadDesktop(hDesk))
        Report(_T("SetThreadDesktop failed with %d\n"), GetLastError());

    // Sleep to allow time for UAC consent prompt to be created on the secure desktop
    Sleep(1000);
    if (SUCCEEDED(init))
    {
        CComPtr<IUIAutomation> pAuto;
        hr = pAuto.CoCreateInstance(CLSID_CUIAutomation8, nullptr, CLSCTX_INPROC_SERVER);
        if (SUCCEEDED(hr))
        {
            HWND hwndCreds = FindWindow(_T("Credential Dialog Xaml Host"), nullptr);
            if (hwndCreds)
            {
                CComPtr<IUIAutomationElement> pWindow;
                hr = pAuto->ElementFromHandle(hwndCreds, &pWindow);
                if (SUCCEEDED(hr) && pWindow)
                {
                    CComPtr<IUIAutomationCacheRequest> pCacheRequest;
                    hr = pAuto->CreateCacheRequest(&pCacheRequest);
                    if (SUCCEEDED(hr) && pCacheRequest)
                    {
                        hr = pCacheRequest->AddPattern(UIA_InvokePatternId);
                    }
                    else
                        Report(_T("CreateCacheRequest, hr: 0x%X, pCacheRequest: %p\n"), hr, pCacheRequest);

                    CComPtr<IUIAutomationCondition> pTypeCondition, pIdCondition, pCondition;
                    CComVariant vButton(UIA_ButtonControlTypeId), vID(L"OkButton");

                    hr = pAuto->CreatePropertyCondition(UIA_ControlTypePropertyId, vButton, &pTypeCondition);
                    hr = pAuto->CreatePropertyCondition(UIA_AutomationIdPropertyId, vID, &pIdCondition);
                    hr = pAuto->CreateAndCondition(pTypeCondition, pIdCondition, &pCondition);

                    if (FAILED(hr) || !pCondition)
                        Report(_T("CreatePropertyCondition, hr: 0x%X, pCondition: %p\n"), hr, pCondition);

                    CComPtr<IUIAutomationElement> pYesButton;
                    hr = pWindow->FindFirstBuildCache(TreeScope_Children, pCondition, pCacheRequest, &pYesButton);
                    if (SUCCEEDED(hr) && pYesButton)
                    {
                        CComPtr<IUIAutomationInvokePattern> pInvoke;
                        hr = pYesButton->GetCachedPatternAs(UIA_InvokePatternId, IID_PPV_ARGS(&pInvoke));
                        if (SUCCEEDED(hr) && pInvoke)
                            pInvoke->Invoke();
                    }
                    else
                        Report(_T("FindFirstBuildCache failed hr: 0x%X, pOK: %p\n"), hr, pYesButton);
                }
                else
                    Report(_T("Failed to obtain IUIAutomation element, hr: 0x%X, pWindow: %p\n"), hr, pWindow);
            }
            else
                Report(_T("Failed to find UAC consent prompt window\n"));
        }
        else
            Report(_T("Failed to create Automation Object, 0x%X\n"), hr);
    }
    else
        Report(_T("COM initialization failed: 0x%X\n"), (HRESULT)init);

    return 0;
}

Was this answer helpful?

1 person found this answer helpful.

1 additional answer

Sort by: Most helpful
  1. Deleted

    This answer has been deleted due to a violation of our Code of Conduct. The answer was manually reported or identified through automated detection before action was taken. Please refer to our Code of Conduct for more information.

    11 deleted comments

    Comments have been turned off. Learn more

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.