Share via

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

David Perry 40 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,566 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.

Answer accepted by question author

Taki Ly (WICLOUD CORPORATION) 1,500 Reputation points Microsoft External Staff Moderator
2026-04-22T10:50:09.23+00:00

Hello @David Perry ,

I would like to offer some suggestions:

1. Certificates: Artifact Signing (formerly Azure Code Signing) provides Identity Validation, satisfies SmartScreen, and meets the cryptographic requirements for uiAccess.

2. Local test is failing: Your self-signed cert is probably fine. The roadblock is likely the File Location. For Windows to honor uiAccess="true", the .exe must be signed and run from a Secure Location (like C:\Program Files\). Running it from D:\ or your Desktop silently strips the uiAccess rights. So, the workaround is copying your self-signed .exe into C:\Program Files\Test\ and run it from there.

3. The Proper Architecture (Win32 APIs) Commercial tools often don't just rely on uiAccess. Since your system service is in Session 0, it should detect the UAC prompt and spawn a worker directly onto the Secure Desktop (Winlogon). The API flow you would P/Invoke in C#: Monitor Desktop: Use OpenInputDesktop to detect when the active desktop switches from Default to Winlogon. Get Session & Token: Use WTSGetActiveConsoleSessionId, WTSQueryUserToken, and DuplicateTokenEx. Spawn Worker: Launch your capture/input agent using CreateProcessAsUser. The step is setting the lpDesktop in the STARTUPINFO structure to @"Winsta0\Winlogon".

That spawned agent might see UAC and your SendInput clicks will register. When UAC closes, that agent terminates, and your Default desktop agent resumes.

I hope these suggestions helpful. Let me know if you need any further helps, and I can try to assist. If you found my response helpful or informative, I would greatly appreciate it if you could provide feedback by following this guide.

Good luck with building your software. Thank you.

Was this answer helpful?

1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

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.