1
0
mirror of https://github.com/veracrypt/VeraCrypt.git synced 2025-11-11 11:08:02 -06:00

Windows: enhance secure desktop handling to try to workaround Windows 11 issue

Several enhancements implemented:
 - replace CreateThread by _beginthreadex to avoid potential issues when using C runtime
 - use an event to notify monitoring thread to stop instead of a volatile boolean
 - perform switch to the regular desktop in the main thread and not in the secure desktop thread
This commit is contained in:
Mounir IDRASSI
2023-07-15 02:59:13 +02:00
parent 49fff71d0a
commit 7ada94d36b

View File

@@ -14085,13 +14085,14 @@ typedef struct
DLGPROC lpDialogFunc; DLGPROC lpDialogFunc;
LPARAM dwInitParam; LPARAM dwInitParam;
INT_PTR retValue; INT_PTR retValue;
BOOL bDlgDisplayed; // set to TRUE if the dialog was displayed on secure desktop
} SecureDesktopThreadParam; } SecureDesktopThreadParam;
typedef struct typedef struct
{ {
LPCWSTR szVCDesktopName; LPCWSTR szVCDesktopName;
HDESK hVcDesktop; HDESK hVcDesktop;
volatile BOOL* pbStopMonitoring; HANDLE hStopEvent; // event to signal when to stop monitoring
} SecureDesktopMonitoringThreadParam; } SecureDesktopMonitoringThreadParam;
#define SECUREDESKTOP_MONOTIR_PERIOD 500 #define SECUREDESKTOP_MONOTIR_PERIOD 500
@@ -14103,11 +14104,12 @@ static unsigned int __stdcall SecureDesktopMonitoringThread( LPVOID lpThreadPara
SecureDesktopMonitoringThreadParam* pMonitorParam = (SecureDesktopMonitoringThreadParam*) lpThreadParameter; SecureDesktopMonitoringThreadParam* pMonitorParam = (SecureDesktopMonitoringThreadParam*) lpThreadParameter;
if (pMonitorParam) if (pMonitorParam)
{ {
volatile BOOL* pbStopMonitoring = pMonitorParam->pbStopMonitoring; HANDLE hStopEvent = pMonitorParam->hStopEvent;
LPCWSTR szVCDesktopName = pMonitorParam->szVCDesktopName; LPCWSTR szVCDesktopName = pMonitorParam->szVCDesktopName;
HDESK hVcDesktop = pMonitorParam->hVcDesktop; HDESK hVcDesktop = pMonitorParam->hVcDesktop;
while (!*pbStopMonitoring) // loop until the stop event is signaled
while (WaitForSingleObject (hStopEvent, SECUREDESKTOP_MONOTIR_PERIOD) == WAIT_TIMEOUT)
{ {
// check that our secure desktop is still the input desktop // check that our secure desktop is still the input desktop
// otherwise, switch to it // otherwise, switch to it
@@ -14135,22 +14137,18 @@ static unsigned int __stdcall SecureDesktopMonitoringThread( LPVOID lpThreadPara
if (bPerformSwitch) if (bPerformSwitch)
SwitchDesktop (hVcDesktop); SwitchDesktop (hVcDesktop);
Sleep (SECUREDESKTOP_MONOTIR_PERIOD);
} }
} }
return 0; return 0;
} }
static DWORD WINAPI SecureDesktopThread(LPVOID lpThreadParameter) static unsigned int __stdcall SecureDesktopThread( LPVOID lpThreadParameter )
{ {
volatile BOOL bStopMonitoring = FALSE;
HANDLE hMonitoringThread = NULL; HANDLE hMonitoringThread = NULL;
unsigned int monitoringThreadID = 0; unsigned int monitoringThreadID = 0;
SecureDesktopThreadParam* pParam = (SecureDesktopThreadParam*) lpThreadParameter; SecureDesktopThreadParam* pParam = (SecureDesktopThreadParam*) lpThreadParameter;
SecureDesktopMonitoringThreadParam monitorParam; SecureDesktopMonitoringThreadParam monitorParam;
HDESK hOriginalDesk = GetThreadDesktop (GetCurrentThreadId ());
BOOL bNewDesktopSet = FALSE; BOOL bNewDesktopSet = FALSE;
// wait for SwitchDesktop to succeed before using it for current thread // wait for SwitchDesktop to succeed before using it for current thread
@@ -14158,38 +14156,48 @@ static DWORD WINAPI SecureDesktopThread(LPVOID lpThreadParameter)
{ {
if (SwitchDesktop (pParam->hDesk)) if (SwitchDesktop (pParam->hDesk))
{ {
bNewDesktopSet = TRUE;
break; break;
} }
Sleep (SECUREDESKTOP_MONOTIR_PERIOD); Sleep (SECUREDESKTOP_MONOTIR_PERIOD);
} }
bNewDesktopSet = SetThreadDesktop (pParam->hDesk);
if (bNewDesktopSet) if (bNewDesktopSet)
{ {
SetThreadDesktop (pParam->hDesk);
// create the thread that will ensure that VeraCrypt secure desktop has always user input // create the thread that will ensure that VeraCrypt secure desktop has always user input
monitorParam.szVCDesktopName = pParam->szDesktopName; // this is done only if the stop event is created successfully
monitorParam.hVcDesktop = pParam->hDesk; HANDLE hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
monitorParam.pbStopMonitoring = &bStopMonitoring; if (hStopEvent)
hMonitoringThread = (HANDLE) _beginthreadex (NULL, 0, SecureDesktopMonitoringThread, (LPVOID) &monitorParam, 0, &monitoringThreadID); {
monitorParam.szVCDesktopName = pParam->szDesktopName;
monitorParam.hVcDesktop = pParam->hDesk;
monitorParam.hStopEvent = hStopEvent;
hMonitoringThread = (HANDLE) _beginthreadex (NULL, 0, SecureDesktopMonitoringThread, (LPVOID) &monitorParam, 0, &monitoringThreadID);
}
pParam->retValue = DialogBoxParamW (pParam->hInstance, pParam->lpTemplateName,
NULL, pParam->lpDialogFunc, pParam->dwInitParam);
if (hMonitoringThread)
{
// notify the monitoring thread to stop
SetEvent(hStopEvent);
WaitForSingleObject (hMonitoringThread, INFINITE);
CloseHandle (hMonitoringThread);
}
if (hStopEvent)
{
CloseHandle (hStopEvent);
}
pParam->bDlgDisplayed = TRUE;
} }
else
pParam->retValue = DialogBoxParamW (pParam->hInstance, pParam->lpTemplateName,
NULL, pParam->lpDialogFunc, pParam->dwInitParam);
if (hMonitoringThread)
{ {
bStopMonitoring = TRUE; pParam->bDlgDisplayed = FALSE;
WaitForSingleObject (hMonitoringThread, INFINITE);
CloseHandle (hMonitoringThread);
}
if (bNewDesktopSet)
{
SetThreadDesktop (hOriginalDesk);
SwitchDesktop (hOriginalDesk);
} }
return 0; return 0;
@@ -14249,6 +14257,7 @@ INT_PTR SecureDesktopDialogBoxParam(
map<DWORD, BOOL> ctfmonBeforeList, ctfmonAfterList; map<DWORD, BOOL> ctfmonBeforeList, ctfmonAfterList;
DWORD desktopAccess = DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_READOBJECTS | DESKTOP_SWITCHDESKTOP | DESKTOP_WRITEOBJECTS; DWORD desktopAccess = DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_READOBJECTS | DESKTOP_SWITCHDESKTOP | DESKTOP_WRITEOBJECTS;
HDESK hSecureDesk; HDESK hSecureDesk;
HDESK hOriginalDesk = GetThreadDesktop (GetCurrentThreadId());
HDESK hInputDesk = NULL; HDESK hInputDesk = NULL;
@@ -14280,8 +14289,10 @@ INT_PTR SecureDesktopDialogBoxParam(
param.lpDialogFunc = lpDialogFunc; param.lpDialogFunc = lpDialogFunc;
param.dwInitParam = dwInitParam; param.dwInitParam = dwInitParam;
param.retValue = 0; param.retValue = 0;
param.bDlgDisplayed = FALSE;
HANDLE hThread = ::CreateThread (NULL, 0, SecureDesktopThread, (LPVOID) &param, 0, NULL); // use _beginthreadex instead of CreateThread because lpDialogFunc may be using the C runtime library
HANDLE hThread = (HANDLE) _beginthreadex (NULL, 0, SecureDesktopThread, (LPVOID) &param, 0, NULL);
if (hThread) if (hThread)
{ {
StringCbCopy(SecureDesktopName, sizeof (SecureDesktopName), szDesktopName); StringCbCopy(SecureDesktopName, sizeof (SecureDesktopName), szDesktopName);
@@ -14289,8 +14300,15 @@ INT_PTR SecureDesktopDialogBoxParam(
WaitForSingleObject (hThread, INFINITE); WaitForSingleObject (hThread, INFINITE);
CloseHandle (hThread); CloseHandle (hThread);
retValue = param.retValue; if (param.bDlgDisplayed)
bSuccess = TRUE; {
// dialog box was indeed displayed in Secure Desktop
retValue = param.retValue;
bSuccess = TRUE;
}
// switch back to original desktop
SwitchDesktop (hOriginalDesk);
} }
CloseDesktop (hSecureDesk); CloseDesktop (hSecureDesk);
@@ -14311,6 +14329,7 @@ INT_PTR SecureDesktopDialogBoxParam(
} }
} }
CloseDesktop(hOriginalDesk);
burn (szDesktopName, sizeof (szDesktopName)); burn (szDesktopName, sizeof (szDesktopName));
} }
} }