Skip to content

Commit

Permalink
Windows: Fix rare cases being stuck in Secure Desktop after it is use…
Browse files Browse the repository at this point in the history
…d for password entry

Cause seems to be IME as documented in KeePass project (https://keepass.info/help/kb/sec_desk.html#ime). We use the same approach as KeePass to disable IME in Secure Desktop.
This commit also add few changes:
  - we switch to secure desktop only if SetThreadDesktop succeeds
  - we call SwitchDesktop to switch to original desktop only if we actually succeeded in displaying secure desktop
  • Loading branch information
idrassi committed Aug 4, 2024
1 parent 71215f1 commit c8b9a73
Showing 1 changed file with 38 additions and 18 deletions.
56 changes: 38 additions & 18 deletions src/Common/Dlgcode.c
Original file line number Diff line number Diff line change
Expand Up @@ -13921,20 +13921,33 @@ static unsigned int __stdcall SecureDesktopThread( LPVOID lpThreadParameter )
StringCbCopy(SecureDesktopName, sizeof (SecureDesktopName), pParam->szDesktopName);
pParam->hDesk = hSecureDesk;

// wait for SwitchDesktop to succeed before using it for current thread
while (true)
bNewDesktopSet = SetThreadDesktop (hSecureDesk);

if (bNewDesktopSet)
{
if (SwitchDesktop (hSecureDesk))
// call ImmDisableIME from imm32.dll to disable IME since it can create issue with secure desktop
// cf: https://keepass.info/help/kb/sec_desk.html#ime
HMODULE hImmDll = LoadLibraryEx (L"imm32.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
if (hImmDll)
{
break;
typedef BOOL (WINAPI *ImmDisableIME_t)(DWORD);
ImmDisableIME_t ImmDisableIME = (ImmDisableIME_t) GetProcAddress (hImmDll, "ImmDisableIME");
if (ImmDisableIME)
{
ImmDisableIME (0);
}
}
Sleep (SECUREDESKTOP_MONOTIR_PERIOD);
}

bNewDesktopSet = SetThreadDesktop (hSecureDesk);
// wait for SwitchDesktop to succeed before using it for current thread
while (true)
{
if (SwitchDesktop (hSecureDesk))
{
break;
}
Sleep (SECUREDESKTOP_MONOTIR_PERIOD);
}

if (bNewDesktopSet)
{
// create the thread that will ensure that VeraCrypt secure desktop has always user input
// this is done only if the stop event is created successfully
HANDLE hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
Expand Down Expand Up @@ -13964,6 +13977,12 @@ static unsigned int __stdcall SecureDesktopThread( LPVOID lpThreadParameter )
}

pParam->bDlgDisplayed = TRUE;

// free imm32.dll handle
if (hImmDll)
{
FreeLibrary (hImmDll);
}
}
else
{
Expand Down Expand Up @@ -14084,19 +14103,20 @@ INT_PTR SecureDesktopDialogBoxParam(
// dialog box was indeed displayed in Secure Desktop
retValue = param.retValue;
bSuccess = TRUE;

// switch back to the original desktop
while (!SwitchDesktop (hOriginalDesk))
{
Sleep (SECUREDESKTOP_MONOTIR_PERIOD);
}

SetThreadDesktop (hOriginalDesk);
}
}

if (param.hDesk)
{
while (!SwitchDesktop (hOriginalDesk))
if (param.hDesk)
{
Sleep (SECUREDESKTOP_MONOTIR_PERIOD);
CloseDesktop (param.hDesk);
}

SetThreadDesktop (hOriginalDesk);

CloseDesktop (param.hDesk);
}

// get the new list of ctfmon.exe processes in order to find the ID of the
Expand Down

0 comments on commit c8b9a73

Please sign in to comment.