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

Windows: Add CLI switches to control memory/screen protection features. Disable non-configurable settings in portable mode

This commit is contained in:
Mounir IDRASSI
2025-06-24 15:48:01 +09:00
parent c1dbcb32e6
commit 5627e7a738
6 changed files with 263 additions and 43 deletions

View File

@@ -185,7 +185,17 @@ Note that turning the password cache off will not clear it (use /w to clear the
</tr> </tr>
<tr> <tr>
<td><em>/protectMemory</em>&nbsp;</td> <td><em>/protectMemory</em>&nbsp;</td>
<td>Activates a mechanism that protects VeraCrypt process memory from being accessed by other non-admin processes.</td> <td>If it is followed by <strong>y</strong> or <strong>yes</strong> or if no parameter is specified: Activates a mechanism that protects VeraCrypt process memory from being accessed by other non-admin processes.
<br>
If it is followed by <strong>n</strong> or <strong>no</strong> (ONLY allowed for portable mode): disables the memory protection mechanism (e.g., /protectMemory n).<br>
</td>
</tr>
<tr>
<td><em>/protectScreen</em>&nbsp;</td>
<td>If it is followed by <strong>y</strong> or <strong>yes</strong> or if no parameter is specified: Activates a mechanism that protects VeraCrypt against screenshots and screen recordings.
<br>
If it is followed by <strong>n</strong> or <strong>no</strong> (ONLY allowed for portable mode): disables the screen protection mechanism (e.g., /protectScreen n).<br>
</td>
</tr> </tr>
<tr> <tr>
<td><em>/signalExit</em>&nbsp;</td> <td><em>/signalExit</em>&nbsp;</td>

View File

@@ -220,6 +220,7 @@ BOOL EMVSupportEnabled = FALSE;
volatile BOOL NeedPeriodicDeviceListUpdate = FALSE; volatile BOOL NeedPeriodicDeviceListUpdate = FALSE;
BOOL DisablePeriodicDeviceListUpdate = FALSE; BOOL DisablePeriodicDeviceListUpdate = FALSE;
BOOL EnableMemoryProtection = FALSE; BOOL EnableMemoryProtection = FALSE;
BOOL EnableScreenProtection = FALSE;
BOOL MemoryProtectionActivated = FALSE; BOOL MemoryProtectionActivated = FALSE;
@@ -3697,11 +3698,9 @@ extern "C" {
ActivateProcessMitigations(); ActivateProcessMitigations();
#ifndef SETUP #ifndef SETUP
// call ActivateMemoryProtection if corresponding setting has been enabled (default is enabled) // initiaize memory protection and screen protection settings using the registry
if (ReadMemoryProtectionConfig()) EnableMemoryProtection = ReadMemoryProtectionConfig();
{ EnableScreenProtection = ReadScreenProtectionConfig();
ActivateMemoryProtection();
}
#endif #endif
return wWinMainCRTStartup(); return wWinMainCRTStartup();
} }
@@ -16201,8 +16200,6 @@ cleanup:
#include <map> #include <map>
#include <mutex> #include <mutex>
static std::once_flag g_configOnce; // ensures one-time read
static std::atomic_bool g_screenProtectionEnabled; // readonly after init
static thread_local HHOOK g_cbtHook = nullptr; // one per thread static thread_local HHOOK g_cbtHook = nullptr; // one per thread
static thread_local int g_protectionRefCount = 0; static thread_local int g_protectionRefCount = 0;
@@ -16210,17 +16207,10 @@ std::map<HWND, WNDPROC> g_MenuWndProcs;
std::map<HWND, bool> g_Initialized; std::map<HWND, bool> g_Initialized;
std::mutex g_MenuMutex; std::mutex g_MenuMutex;
static void InitScreenProtectionFlag()
{
// Runs exactly once thanks to std::call_once
BOOL enabled = ReadScreenProtectionConfig();
g_screenProtectionEnabled.store(enabled, std::memory_order_release);
}
static bool IsScreenProtectionEnabled() static bool IsScreenProtectionEnabled()
{ {
std::call_once(g_configOnce, InitScreenProtectionFlag); // EnableScreenProtection is populated at startup based on registry settings and command line options
return g_screenProtectionEnabled.load(std::memory_order_acquire); return EnableScreenProtection? true: false;
} }

View File

@@ -174,6 +174,7 @@ extern BOOL EMVSupportEnabled;
extern volatile BOOL NeedPeriodicDeviceListUpdate; extern volatile BOOL NeedPeriodicDeviceListUpdate;
extern BOOL DisablePeriodicDeviceListUpdate; extern BOOL DisablePeriodicDeviceListUpdate;
extern BOOL EnableMemoryProtection; extern BOOL EnableMemoryProtection;
extern BOOL EnableScreenProtection;
#ifndef SETUP #ifndef SETUP
extern BOOL bLanguageSetInSetup; extern BOOL bLanguageSetInSetup;

View File

@@ -885,16 +885,19 @@ void ExtractCommandLine (HWND hwndDlg, wchar_t *lpszCommandLine)
enum enum
{ {
OptionEnableMemoryProtection, OptionEnableMemoryProtection,
OptionEnableScreenProtection,
}; };
argument args[]= argument args[]=
{ {
{ OptionEnableMemoryProtection, L"/protectMemory", NULL, FALSE }, { OptionEnableMemoryProtection, L"/protectMemory", NULL, FALSE },
{ OptionEnableScreenProtection, L"/protectScreen", NULL, FALSE },
}; };
argumentspec as; argumentspec as;
int x; int x;
wchar_t szTmp[32] = {0};
if (lpszCommandLineArgs[i] == NULL) if (lpszCommandLineArgs[i] == NULL)
continue; continue;
@@ -908,7 +911,33 @@ void ExtractCommandLine (HWND hwndDlg, wchar_t *lpszCommandLine)
{ {
case OptionEnableMemoryProtection: case OptionEnableMemoryProtection:
if (HAS_ARGUMENT == GetArgumentValue (lpszCommandLineArgs,
&i, nNoCommandLineArgs, szTmp, ARRAYSIZE (szTmp)))
{
if ((!_wcsicmp (szTmp, L"no") || !_wcsicmp (szTmp, L"n")) && IsNonInstallMode())
EnableMemoryProtection = FALSE;
else if (!_wcsicmp (szTmp, L"yes") || !_wcsicmp (szTmp, L"y"))
EnableMemoryProtection = TRUE; EnableMemoryProtection = TRUE;
else
AbortProcess ("COMMAND_LINE_ERROR");
}
else
EnableMemoryProtection = TRUE;
break;
case OptionEnableScreenProtection:
if (HAS_ARGUMENT == GetArgumentValue (lpszCommandLineArgs,
&i, nNoCommandLineArgs, szTmp, ARRAYSIZE (szTmp)))
{
if ((!_wcsicmp (szTmp, L"no") || !_wcsicmp (szTmp, L"n")) && IsNonInstallMode())
EnableScreenProtection = FALSE;
else if (!_wcsicmp (szTmp, L"yes") || !_wcsicmp (szTmp, L"y"))
EnableScreenProtection = TRUE;
else
AbortProcess ("COMMAND_LINE_ERROR");
}
else
EnableScreenProtection = TRUE;
break; break;
default: default:
@@ -966,12 +995,6 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
RestoreDefaultKeyFilesParam (); RestoreDefaultKeyFilesParam ();
} }
if (EnableMemoryProtection)
{
/* Protect this process memory from being accessed by non-admin users */
ActivateMemoryProtection ();
}
InitMainDialog (hwndDlg); InitMainDialog (hwndDlg);
// Quit // Quit
@@ -1087,6 +1110,47 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, wchar_t *lpszCommandLine, int nCmdShow) int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, wchar_t *lpszCommandLine, int nCmdShow)
{ {
int status; int status;
int argc;
LPWSTR *argv = CommandLineToArgvW (GetCommandLineW(), &argc);
for (int i = 0; argv && i < argc; i++)
{
if (_wcsicmp (argv[i], L"/protectScreen") == 0)
{
if ((i < argc - 1) && _wcsicmp (argv[i + 1], L"no") == 0)
{
// Disabling screen protection is only allowed in portable mode
if (IsNonInstallMode())
EnableScreenProtection = FALSE;
}
else
{
EnableScreenProtection = TRUE;
}
}
if (_wcsicmp (argv[i], L"/protectMemory") == 0)
{
if ((i < argc - 1) && _wcsicmp (argv[i + 1], L"no") == 0)
{
// Disabling memory protection is only allowed in portable mode
if (IsNonInstallMode())
EnableMemoryProtection = FALSE;
}
else
{
EnableMemoryProtection = TRUE;
}
}
}
LocalFree (argv); // free memory allocated by CommandLineToArgvW
if (EnableMemoryProtection)
{
/* Protect this process memory from being accessed by non-admin users */
ActivateMemoryProtection ();
}
ScreenCaptureBlocker blocker; ScreenCaptureBlocker blocker;
atexit (VeraCryptExpander::localcleanup); atexit (VeraCryptExpander::localcleanup);
SetProcessShutdownParameters (0x100, 0); SetProcessShutdownParameters (0x100, 0);

View File

@@ -6265,12 +6265,6 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
ExtractCommandLine (hwndDlg, (wchar_t *) lParam); ExtractCommandLine (hwndDlg, (wchar_t *) lParam);
if (EnableMemoryProtection)
{
/* Protect this process memory from being accessed by non-admin users */
ActivateMemoryProtection ();
}
if (ComServerMode) if (ComServerMode)
{ {
InitDialog (hwndDlg); InitDialog (hwndDlg);
@@ -9175,6 +9169,7 @@ void ExtractCommandLine (HWND hwndDlg, wchar_t *lpszCommandLine)
OptionQuickFormat, OptionQuickFormat,
OptionFastCreateFile, OptionFastCreateFile,
OptionEnableMemoryProtection, OptionEnableMemoryProtection,
OptionEnableScreenProtection,
OptionKeyfile, OptionKeyfile,
OptionSecureDesktop, OptionSecureDesktop,
}; };
@@ -9201,6 +9196,7 @@ void ExtractCommandLine (HWND hwndDlg, wchar_t *lpszCommandLine)
{ OptionQuickFormat, L"/quick", NULL, FALSE }, { OptionQuickFormat, L"/quick", NULL, FALSE },
{ OptionFastCreateFile, L"/fastcreatefile", NULL, FALSE }, { OptionFastCreateFile, L"/fastcreatefile", NULL, FALSE },
{ OptionEnableMemoryProtection, L"/protectMemory", NULL, FALSE }, { OptionEnableMemoryProtection, L"/protectMemory", NULL, FALSE },
{ OptionEnableScreenProtection, L"/protectScreen", NULL, FALSE },
{ OptionKeyfile, L"/keyfile", L"/k", FALSE }, { OptionKeyfile, L"/keyfile", L"/k", FALSE },
{ OptionSecureDesktop, L"/secureDesktop", NULL, FALSE }, { OptionSecureDesktop, L"/secureDesktop", NULL, FALSE },
@@ -9564,9 +9560,39 @@ void ExtractCommandLine (HWND hwndDlg, wchar_t *lpszCommandLine)
break; break;
case OptionEnableMemoryProtection: case OptionEnableMemoryProtection:
{
wchar_t szTmp[16] = { 0 };
if (HAS_ARGUMENT == GetArgumentValue(lpszCommandLineArgs,
&i, nNoCommandLineArgs, szTmp, ARRAYSIZE(szTmp)))
{
if ((!_wcsicmp(szTmp, L"no") || !_wcsicmp(szTmp, L"n")) && IsNonInstallMode())
EnableMemoryProtection = FALSE;
else if (!_wcsicmp(szTmp, L"yes") || !_wcsicmp(szTmp, L"y"))
EnableMemoryProtection = TRUE;
else
AbortProcess("COMMAND_LINE_ERROR");
}
else
EnableMemoryProtection = TRUE; EnableMemoryProtection = TRUE;
break; break;
}
case OptionEnableScreenProtection:
{
wchar_t szTmp[16] = { 0 };
if (HAS_ARGUMENT == GetArgumentValue(lpszCommandLineArgs,
&i, nNoCommandLineArgs, szTmp, ARRAYSIZE(szTmp)))
{
if ((!_wcsicmp(szTmp, L"no") || !_wcsicmp(szTmp, L"n")) && IsNonInstallMode())
EnableScreenProtection = FALSE;
else if (!_wcsicmp(szTmp, L"yes") || !_wcsicmp(szTmp, L"y"))
EnableScreenProtection = TRUE;
else
AbortProcess("COMMAND_LINE_ERROR");
}
else
EnableScreenProtection = TRUE;
break;
}
case OptionHistory: case OptionHistory:
{ {
wchar_t szTmp[8] = {0}; wchar_t szTmp[8] = {0};
@@ -10593,6 +10619,47 @@ static void AfterWMInitTasks (HWND hwndDlg)
int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, wchar_t *lpszCommandLine, int nCmdShow) int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, wchar_t *lpszCommandLine, int nCmdShow)
{ {
int status; int status;
int argc;
LPWSTR *argv = CommandLineToArgvW (GetCommandLineW(), &argc);
for (int i = 0; argv && i < argc; i++)
{
if (_wcsicmp (argv[i], L"/protectScreen") == 0)
{
if ((i < argc - 1) && _wcsicmp (argv[i + 1], L"no") == 0)
{
// Disabling screen protection is only allowed in portable mode
if (IsNonInstallMode())
EnableScreenProtection = FALSE;
}
else
{
EnableScreenProtection = TRUE;
}
}
if (_wcsicmp (argv[i], L"/protectMemory") == 0)
{
if ((i < argc - 1) && _wcsicmp (argv[i + 1], L"no") == 0)
{
// Disabling memory protection is only allowed in portable mode
if (IsNonInstallMode())
EnableMemoryProtection = FALSE;
}
else
{
EnableMemoryProtection = TRUE;
}
}
}
LocalFree (argv); // free memory allocated by CommandLineToArgvW
if (EnableMemoryProtection)
{
/* Protect this process memory from being accessed by non-admin users */
ActivateMemoryProtection ();
}
ScreenCaptureBlocker blocker; ScreenCaptureBlocker blocker;
atexit (localcleanup); atexit (localcleanup);

View File

@@ -7177,12 +7177,6 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
AbortProcess ("COMMAND_LINE_ERROR"); AbortProcess ("COMMAND_LINE_ERROR");
} }
if (EnableMemoryProtection)
{
/* Protect this process memory from being accessed by non-admin users */
ActivateMemoryProtection ();
}
if (ComServerMode) if (ComServerMode)
{ {
InitDialog (hwndDlg); InitDialog (hwndDlg);
@@ -9238,6 +9232,7 @@ void ExtractCommandLine (HWND hwndDlg, wchar_t *lpszCommandLine)
OptionSecureDesktop, OptionSecureDesktop,
OptionDisableDeviceUpdate, OptionDisableDeviceUpdate,
OptionEnableMemoryProtection, OptionEnableMemoryProtection,
OptionEnableScreenProtection,
OptionSignalExit, OptionSignalExit,
CommandUnmount, CommandUnmount,
}; };
@@ -9269,6 +9264,7 @@ void ExtractCommandLine (HWND hwndDlg, wchar_t *lpszCommandLine)
{ OptionSecureDesktop, L"/secureDesktop", NULL, FALSE }, { OptionSecureDesktop, L"/secureDesktop", NULL, FALSE },
{ OptionDisableDeviceUpdate, L"/disableDeviceUpdate", NULL, FALSE }, { OptionDisableDeviceUpdate, L"/disableDeviceUpdate", NULL, FALSE },
{ OptionEnableMemoryProtection, L"/protectMemory", NULL, FALSE }, { OptionEnableMemoryProtection, L"/protectMemory", NULL, FALSE },
{ OptionEnableScreenProtection, L"/protectScreen", NULL, FALSE },
{ OptionSignalExit, L"/signalExit", NULL, FALSE }, { OptionSignalExit, L"/signalExit", NULL, FALSE },
{ CommandUnmount, L"/unmount", L"/u", FALSE }, { CommandUnmount, L"/unmount", L"/u", FALSE },
}; };
@@ -9369,9 +9365,38 @@ void ExtractCommandLine (HWND hwndDlg, wchar_t *lpszCommandLine)
case OptionEnableMemoryProtection: case OptionEnableMemoryProtection:
{ {
wchar_t szTmp[16] = { 0 };
if (HAS_ARGUMENT == GetArgumentValue(lpszCommandLineArgs,
&i, nNoCommandLineArgs, szTmp, ARRAYSIZE(szTmp)))
{
if ((!_wcsicmp(szTmp, L"no") || !_wcsicmp(szTmp, L"n")) && IsNonInstallMode())
EnableMemoryProtection = FALSE;
else if (!_wcsicmp(szTmp, L"yes") || !_wcsicmp(szTmp, L"y"))
EnableMemoryProtection = TRUE; EnableMemoryProtection = TRUE;
else
AbortProcess("COMMAND_LINE_ERROR");
} }
else
EnableMemoryProtection = TRUE;
break; break;
}
case OptionEnableScreenProtection:
{
wchar_t szTmp[16] = { 0 };
if (HAS_ARGUMENT == GetArgumentValue(lpszCommandLineArgs,
&i, nNoCommandLineArgs, szTmp, ARRAYSIZE(szTmp)))
{
if ((!_wcsicmp(szTmp, L"no") || !_wcsicmp(szTmp, L"n")) && IsNonInstallMode())
EnableScreenProtection = FALSE;
else if (!_wcsicmp(szTmp, L"yes") || !_wcsicmp(szTmp, L"y"))
EnableScreenProtection = TRUE;
else
AbortProcess("COMMAND_LINE_ERROR");
}
else
EnableScreenProtection = TRUE;
break;
}
case OptionSignalExit: case OptionSignalExit:
if (HAS_ARGUMENT == GetArgumentValue (lpszCommandLineArgs, &i, if (HAS_ARGUMENT == GetArgumentValue (lpszCommandLineArgs, &i,
@@ -10172,14 +10197,18 @@ static BOOL StartSystemFavoritesService ()
int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, wchar_t *lpszCommandLine, int nCmdShow) int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, wchar_t *lpszCommandLine, int nCmdShow)
{ {
int argc; int argc;
ScreenCaptureBlocker blocker;
LPWSTR *argv = CommandLineToArgvW (GetCommandLineW(), &argc); LPWSTR *argv = CommandLineToArgvW (GetCommandLineW(), &argc);
// We don't need screen protection in the service or in the post OS upgrade process
if (argv && argc == 2 && wstring (TC_SYSTEM_FAVORITES_SERVICE_CMDLINE_OPTION) == argv[1]) if (argv && argc == 2 && wstring (TC_SYSTEM_FAVORITES_SERVICE_CMDLINE_OPTION) == argv[1])
{
LocalFree (argv); // free memory allocated by CommandLineToArgvW
return StartSystemFavoritesService() ? 0 : 1; return StartSystemFavoritesService() ? 0 : 1;
}
if (argv && argc == 2 && wstring (VC_WINDOWS_UPGRADE_POSTOOBE_CMDLINE_OPTION) == argv[1]) if (argv && argc == 2 && wstring (VC_WINDOWS_UPGRADE_POSTOOBE_CMDLINE_OPTION) == argv[1])
{ {
LocalFree (argv); // free memory allocated by CommandLineToArgvW
InitOSVersionInfo(); InitOSVersionInfo();
try try
{ {
@@ -10194,6 +10223,47 @@ int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, wchar_t *lpsz
return 0; return 0;
} }
for (int i = 0; argv && i < argc; i++)
{
if (_wcsicmp (argv[i], L"/protectScreen") == 0)
{
if ((i < argc - 1) && _wcsicmp (argv[i + 1], L"no") == 0)
{
// Disabling screen protection is only allowed in portable mode
if (IsNonInstallMode())
EnableScreenProtection = FALSE;
}
else
{
EnableScreenProtection = TRUE;
}
}
if (_wcsicmp (argv[i], L"/protectMemory") == 0)
{
if ((i < argc - 1) && _wcsicmp (argv[i + 1], L"no") == 0)
{
// Disabling memory protection is only allowed in portable mode
if (IsNonInstallMode())
EnableMemoryProtection = FALSE;
}
else
{
EnableMemoryProtection = TRUE;
}
}
}
LocalFree (argv); // free memory allocated by CommandLineToArgvW
if (EnableMemoryProtection)
{
/* Protect this process memory from being accessed by non-admin users */
ActivateMemoryProtection ();
}
// activate screen protection if it is not disabled
ScreenCaptureBlocker blocker;
int status; int status;
atexit (localcleanup); atexit (localcleanup);
SetProcessShutdownParameters (0x100, 0); SetProcessShutdownParameters (0x100, 0);
@@ -11755,7 +11825,7 @@ static BOOL CALLBACK PerformanceSettingsDlgProc (HWND hwndDlg, UINT msg, WPARAM
EnableWindow (GetDlgItem (hwndDlg, IDC_ENABLE_CPU_RNG), FALSE); EnableWindow (GetDlgItem (hwndDlg, IDC_ENABLE_CPU_RNG), FALSE);
} }
if (IsRamEncryptionSupported()) if (!IsNonInstallMode() && IsRamEncryptionSupported()) // RAM encryption is not supported in portable mode
{ {
CheckDlgButton (hwndDlg, IDC_ENABLE_RAM_ENCRYPTION, (driverConfig & VC_DRIVER_CONFIG_ENABLE_RAM_ENCRYPTION) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton (hwndDlg, IDC_ENABLE_RAM_ENCRYPTION, (driverConfig & VC_DRIVER_CONFIG_ENABLE_RAM_ENCRYPTION) ? BST_CHECKED : BST_UNCHECKED);
} }
@@ -11765,8 +11835,26 @@ static BOOL CALLBACK PerformanceSettingsDlgProc (HWND hwndDlg, UINT msg, WPARAM
EnableWindow (GetDlgItem (hwndDlg, IDC_ENABLE_RAM_ENCRYPTION), FALSE); EnableWindow (GetDlgItem (hwndDlg, IDC_ENABLE_RAM_ENCRYPTION), FALSE);
} }
if (IsNonInstallMode())
{
CheckDlgButton (hwndDlg, IDC_DISABLE_MEMORY_PROTECTION, EnableMemoryProtection ? BST_UNCHECKED : BST_CHECKED);
EnableWindow (GetDlgItem (hwndDlg, IDC_DISABLE_MEMORY_PROTECTION), FALSE);
}
else
{
CheckDlgButton (hwndDlg, IDC_DISABLE_MEMORY_PROTECTION, ReadMemoryProtectionConfig() ? BST_UNCHECKED : BST_CHECKED); CheckDlgButton (hwndDlg, IDC_DISABLE_MEMORY_PROTECTION, ReadMemoryProtectionConfig() ? BST_UNCHECKED : BST_CHECKED);
}
if (IsNonInstallMode())
{
CheckDlgButton (hwndDlg, IDC_DISABLE_SCREEN_PROTECTION, EnableScreenProtection ? BST_UNCHECKED : BST_CHECKED);
EnableWindow (GetDlgItem (hwndDlg, IDC_DISABLE_SCREEN_PROTECTION), FALSE);
}
else
{
CheckDlgButton (hwndDlg, IDC_DISABLE_SCREEN_PROTECTION, ReadScreenProtectionConfig() ? BST_UNCHECKED : BST_CHECKED); CheckDlgButton (hwndDlg, IDC_DISABLE_SCREEN_PROTECTION, ReadScreenProtectionConfig() ? BST_UNCHECKED : BST_CHECKED);
}
size_t cpuCount = GetCpuCount(NULL); size_t cpuCount = GetCpuCount(NULL);