microsoft/Windows.UI.Composition-Win32-Samples

Cannot use IGraphicsCaptureItemInterop::CreateForWindow with electron apps

YueLu0116 opened this issue · 6 comments

My Windows screen-capture sdk is built on winrt(c++) and work with electron through c++ addons. However, every time I call CreateForMonitor, it will throw an access-deined exception. How can I solve this issue?

Windows version: Windows 10 20H2 (19042.1706)
What I have tried:

  1. run the electron application as Administrator
  2. start the electron app with command line arguements: --no-sandbox
  3. I check the result of GetSidSubAuthority: SECURITY_MANDATORY_HIGH_RID

Some similar but unsolved issues:

  1. #49
  2. #55

IGraphicsCaptureItemInterop is not available to LowIL callers, which would include the JavaScript process in Chromium. You'll need to either construct the item from at least a MediumIL process and marshal it to the LowIL process or use the newer TryCreateFromWindowId method added in Windows 11.

IGraphicsCaptureItemInterop is not available to LowIL callers, which would include the JavaScript process in Chromium. You'll need to either construct the item from at least a MediumIL process and marshal it to the LowIL process or use the newer TryCreateFromWindowId method added in Windows 11.

I call GetSidSubAuthority before calling CreateForMonitor and I always get SECURITY_MANDATORY_HIGH_RID. Does it mean the process is HighIL?

How are you calling GetSidSubAuthority? What does it say when you query for TokenIsAppContainer from the process token? Unfortunately, I'm not very familiar with Electron, so I'm not sure how your steps are affecting the environment when we go to inspect the process token on the system side.

@robmikh
Today I query TokenIsAppContainer following your advice. After this query, I call CreateForMonitor and everything works fine. Don't know what happened...

void IsAppContainer() {
	HANDLE hToken = nullptr;
	if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
		DWORD dwSize = 0;
		BOOL fIsAppContainerProcess;
		if (!GetTokenInformation(hToken, TokenIsAppContainer, &fIsAppContainerProcess, sizeof(BOOL), &dwSize) ||
			dwSize != sizeof BOOL) {
			fIsAppContainerProcess = false;
		}
		if (fIsAppContainerProcess) {
			LOG("It is an app container. [fIsAppContainerProcess={}]", fIsAppContainerProcess);
		}
		else {
			LOG("It is NOT an app container. [fIsAppContainerProcess={}]", fIsAppContainerProcess);
		}
	}
	else {
		LOG("OpenProcessToken() error {}\n", (unsigned long)(GetLastError()));
	}
}

Codes for calling GetSidSubAuthority:

DWORD GetProcessIL(TOKEN_INFORMATION_CLASS tokenInfoCls)
{
	DWORD dwRet = 0; {
		HANDLE hToken = NULL;
		if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
			DWORD dwSize = 0;
			// determine information length
			if (!GetTokenInformation(hToken, tokenInfoCls, NULL, 0, &dwSize) &&
				GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
				PTOKEN_MANDATORY_LABEL TokenInfo = (PTOKEN_MANDATORY_LABEL)malloc(dwSize);
				if (TokenInfo) {
					// get an actual information
					if (GetTokenInformation(hToken, tokenInfoCls, TokenInfo, dwSize, &dwSize)) {
						// get the integrity level
						dwRet = *GetSidSubAuthority(
							TokenInfo->Label.Sid,
							(DWORD)(*GetSidSubAuthorityCount(TokenInfo->Label.Sid) - 1)
						);
					}
					else {
						LOG("GetSidSubAuthorityCount() error {}\n", (unsigned long)GetLastError());
					}
					free(TokenInfo);
				}
				else {
					LOG("Token allocation error {}\n", (unsigned long)(GetLastError()));
				}
			}
			else {
				LOG("GetTokenInformation() error {}\n", (unsigned long)(GetLastError()));
			}
			CloseHandle(hToken);
		}
		else {
			LOG("OpenProcessToken() error {}\n", (unsigned long)(GetLastError()));
		}
	}
	return dwRet;
}

Hi @YueLu0116, so this worked after you called both of those functions? Is it that you stopped calling it as an admin?

Hi @YueLu0116, so this worked after you called both of those functions? Is it that you stopped calling it as an admin?

Do you resolve this problem when as admin