I have a project that I tried to run and it wasted more than 30% CPU. why?
The code is for a shortcut program and some reminders.
I am using visual studio 2017 c++ windows 10 Core Intel/i7
the command line:
/Yu"stdafx.h" /GS /analyze- /W3 /Zc:wchar_t /ZI /Gm /Od /sdl /Fd"Debug\vc141.pdb" /Zc:inline /fp:precise /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /Oy- /MDd /Fa"Debug\" /EHsc /nologo /Fo"Debug\" /Fp"Debug\Clear.pch" /diagnostics:classic
the code:
#include "stdafx.h"
#include <Windows.h>
#include <shellapi.h>
bool pressed(int key) { return GetAsyncKeyState(key); }
namespace Main {
///to hide the console
void Main()
{
SetWindowPos(GetConsoleWindow(), nullptr, 0, 0, 0, 0, SWP_HIDEWINDOW);
}
///the shortcuts
void Main1() {
while (true) {
///Win-C = chrome
if (pressed(VK_LWIN)&&pressed('C')) system("chrome http://www.google.com");
///Menu = battery message
if (pressed(VK_APPS)) {
SYSTEM_POWER_STATUS a;
GetSystemPowerStatus(&a);
char title[15]; sprintf(title, "%d%% battery%s", a.BatteryLifePercent, a.BatteryFlag & 8 ? ", charging" : "");
char disp[100]; sprintf(disp, "You have %d hours and %d minutes left...", a.BatteryLifeTime / 3600 % 60, a.BatteryLifeTime / 60 % 60);
MessageBoxA(nullptr, disp, title, 0);
}
if (pressed(VK_LWIN) && pressed(VK_DELETE)) SHEmptyRecycleBinA(nullptr, "", 0);
if (pressed(VK_LWIN) && pressed('V')) system("C:\\Users\\steven\\source\\repos\\Clear\\Clear.sln");
if (pressed(VK_LWIN) && pressed('Z')) system("start cmd");
Sleep(GetDoubleClickTime());
}
}
///time
void Main2() {
while (true) {
SYSTEMTIME t;
GetSystemTime(&t);
if (t.wDayOfWeek != 4 && t.wDayOfWeek != 5 && t.wHour == 0 && t.wMinute == 0 && t.wSecond == 0 && t.wMilliseconds == 0) MessageBoxA(nullptr, "Its 00:00", "Sleep", 0);
if (t.wDayOfWeek == 0 && t.wHour == 15 && t.wMinute == 10 && t.wSecond == 0 && t.wMilliseconds == 0) MessageBoxA(nullptr, "Go to the Technion", "תירגול", 0);
if ((t.wDayOfWeek == 1 || t.wDayOfWeek == 2) && t.wHour == 12 && t.wMinute == 25 && t.wSecond == 0 && t.wMilliseconds == 0) MessageBoxA(nullptr, "Go to the lab", "Math is over", 0);
if (t.wDayOfWeek == 3 && t.wHour == 9 && t.wMinute == 35 && t.wSecond == 0 && t.wMilliseconds == 0) MessageBoxA(nullptr, "Go to the class", "Math is over", 0);
if (t.wDayOfWeek == 4 && t.wHour == 10 && t.wMinute == 50 && t.wSecond == 0 && t.wMilliseconds == 0) MessageBoxA(nullptr, "Go to the class", "Math is over", 0);
}
}
///the exit shortcut
void Main0() {
while (true) {
if (pressed(VK_LMENU) && pressed(VK_RMENU)) if (MessageBoxA(nullptr, "Do you want to exit?", "ShortCut", MB_YESNO|MB_ICONINFORMATION) == IDYES) exit(0);
Sleep(GetDoubleClickTime());
}
}
}
#include <thread>
using namespace std;
int main(){
using namespace Main;
thread a[4]={thread(Main), thread(Main0), thread(Main1), thread(Main2)};
for(thread& b:a) b.join();
return 0;}
Main2() is very processor intensive, as it's a tight loop.
As a crude fix, consider a Sleep on that thread too.
The correct way to find out is with a profiller; visual studio has one built in which you should get some practice with; since it would not only highlight your high CPU; but also which thread.
Knowing which thread, in this example, would be enough information to answer your question. If you plan to write threaded code you should get to grips with more of the tools in VS since threading gets very complex, very fast.
Related
I've created simple test which creates two thread; first one (WorkerThreadFun) executes infinite loop and second one (WorkerGuardThreadFun) terminates it with small timeout.
Thread to be terminated does not seem to do expicit allocation (at least inside WorkerThreadFun) and uses only stack variables of plain C type so I hope the stack will be deallocated by TerminateThread() with CloseHandle().
By some reason this test leaks memory on my Win7.
Where is the unbalanced heap allocation?
#include <windows.h>
#include <synchapi.h>
#include <assert.h>
#include <stdio.h>
#define STK_SIZE 4097
typedef enum
{
GRD_IDLE,
GRD_READY,
GRD_TASKSTARTING,
GRD_TASKWAITING
} GuardThreadState;
typedef struct
{
HANDLE mHworkerThread;
HANDLE mHworkerGroupThread;
volatile int mIsWorkerStarted;
GuardThreadState mGuardThreadState;
CRITICAL_SECTION mLock;
CONDITION_VARIABLE mThreadReadyCond;
CONDITION_VARIABLE mStartTaskCond;
CONDITION_VARIABLE mTaskFinishedCond;
} WorkerThreadHolder;
/*
typedef VOID(WINAPI *PRtlFreeUserThreadStack)(HANDLE hProcess, HANDLE hThread);
static PRtlFreeUserThreadStack RtlFreeUserThreadStack = NULL;
*/
DWORD WINAPI WorkerThreadFun(_In_ LPVOID p);
DWORD WINAPI WorkerGuardThreadFun(_In_ LPVOID p);
void Start(WorkerThreadHolder *workerThreadHolderPtr);
void ExecuteTask(WorkerThreadHolder *workerThreadHolderPtr);
/*----------------------------------------------------------------------------*/
DWORD WINAPI WorkerThreadFun(_In_ LPVOID p)
{
/* use stack variables only in this thread in hope the stack will be deallocated by TerminateThread() */
WorkerThreadHolder *workerThreadHolderPtr = (WorkerThreadHolder *)p;
volatile int i;
workerThreadHolderPtr->mIsWorkerStarted = 1;
/*WakeAllConditionVariable(&workerThreadHolderPtr->mThreadReadyCond);*/
/* do nothing for infinite long time */
for(i = 0;; ++i)
i = i;
/*WakeAllConditionVariable(&workerThreadHolderPtr->mTaskFinishedCond);*/
return 0;
}
DWORD WINAPI WorkerGuardThreadFun(_In_ LPVOID p)
{
const DWORD taskExecutionTimeoutInMillisec = 1;
WorkerThreadHolder *workerThreadHolderPtr = (WorkerThreadHolder *)p;
EnterCriticalSection(&workerThreadHolderPtr->mLock);
workerThreadHolderPtr->mGuardThreadState = GRD_READY;
WakeAllConditionVariable(&workerThreadHolderPtr->mThreadReadyCond);
for (;;)
{
for (;;)
{
SleepConditionVariableCS(
&workerThreadHolderPtr->mStartTaskCond,
&workerThreadHolderPtr->mLock,
INFINITE);
if (workerThreadHolderPtr->mGuardThreadState == GRD_TASKSTARTING)
break;
}
workerThreadHolderPtr->mGuardThreadState = GRD_TASKWAITING;
{
BOOL isTaskFinishedOk = FALSE;
for (;;)
{
isTaskFinishedOk =
SleepConditionVariableCS(
&workerThreadHolderPtr->mTaskFinishedCond,
&workerThreadHolderPtr->mLock,
taskExecutionTimeoutInMillisec);
if (!isTaskFinishedOk)
break;
}
if (isTaskFinishedOk)
{
/* never happens in this test */
}
else
{
BOOL isClosed;
TerminateThread(workerThreadHolderPtr->mHworkerThread, 0);
/*if (RtlFreeUserThreadStack != NULL)
RtlFreeUserThreadStack(GetCurrentProcess(), workerThreadHolderPtr->mHworkerThread);*/
isClosed = CloseHandle(workerThreadHolderPtr->mHworkerThread);
workerThreadHolderPtr->mIsWorkerStarted = 0;
workerThreadHolderPtr->mHworkerThread =
CreateThread(
NULL,
STK_SIZE,
WorkerThreadFun,
(PVOID)workerThreadHolderPtr,
STACK_SIZE_PARAM_IS_A_RESERVATION,
NULL);
}
}
workerThreadHolderPtr->mGuardThreadState = GRD_READY;
WakeAllConditionVariable(&workerThreadHolderPtr->mThreadReadyCond);
}
return 0;
}
void Start(WorkerThreadHolder *workerThreadHolderPtr)
{
workerThreadHolderPtr->mGuardThreadState = GRD_IDLE;
workerThreadHolderPtr->mIsWorkerStarted = 0;
InitializeConditionVariable(&workerThreadHolderPtr->mThreadReadyCond);
InitializeConditionVariable(&workerThreadHolderPtr->mStartTaskCond);
InitializeConditionVariable(&workerThreadHolderPtr->mTaskFinishedCond);
InitializeCriticalSection(&workerThreadHolderPtr->mLock);
workerThreadHolderPtr->mHworkerThread =
CreateThread(
NULL,
STK_SIZE,
WorkerThreadFun,
(LPVOID)workerThreadHolderPtr,
STACK_SIZE_PARAM_IS_A_RESERVATION,
NULL);
workerThreadHolderPtr->mHworkerGroupThread =
CreateThread(
NULL,
0,
WorkerGuardThreadFun,
(LPVOID)workerThreadHolderPtr,
0,
NULL);
}
void ExecuteTask(WorkerThreadHolder *workerThreadHolderPtr)
{
assert(workerThreadHolderPtr->mHworkerThread != NULL);
assert(workerThreadHolderPtr->mHworkerGroupThread != NULL);
EnterCriticalSection(&workerThreadHolderPtr->mLock);
for (;;)
{
if (workerThreadHolderPtr->mGuardThreadState == GRD_READY /* && workerThreadHolderPtr->mIsWorkerStarted != 0 */)
break;
SleepConditionVariableCS(
&workerThreadHolderPtr->mThreadReadyCond,
&workerThreadHolderPtr->mLock,
INFINITE);
}
/* just poll */
for (;;)
{
if (workerThreadHolderPtr->mIsWorkerStarted != 0)
break;
}
workerThreadHolderPtr->mGuardThreadState = GRD_TASKSTARTING;
WakeAllConditionVariable(&workerThreadHolderPtr->mStartTaskCond);
LeaveCriticalSection(&workerThreadHolderPtr->mLock);
}
/*----------------------------------------------------------------------------*/
int main(int argc, char *argv[])
{
int i;
WorkerThreadHolder workerThreadHolder;
/*
HMODULE NTLibrary = GetModuleHandleW(L"ntdll.dll");
RtlFreeUserThreadStack = (PRtlFreeUserThreadStack)GetProcAddress(NTLibrary, "RtlFreeUserThreadStack");
*/
Start(&workerThreadHolder);
for(i = 0;; ++i)
{
ExecuteTask(&workerThreadHolder);
printf("%d Execution started...\n", i);
/*fflush(stdout);*/
}
return 0;
}
Tested with Visual Studio 2015, vc command line:
/GS- /analyze- /W3 /Zc:wchar_t /ZI /Gm /Od /Fd"Debug\vc140.pdb" /Zc:inline /fp:precise /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /Gd /Oy /MDd /Fa"Debug\" /nologo /Fo"Debug\" /Fp"Debug\ConsoleApplication1.pch"
linker:
/OUT:"C:\Users\cherney\documents\visual studio 2015\Projects\ConsoleApplication1\Debug\ConsoleApplication1.exe" /MANIFEST /NXCOMPAT /PDB:"C:\Users\cherney\documents\visual studio 2015\Projects\ConsoleApplication1\Debug\ConsoleApplication1.pdb" /DYNAMICBASE "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /DEBUG /MACHINE:X86 /INCREMENTAL /PGD:"C:\Users\cherney\documents\visual studio 2015\Projects\ConsoleApplication1\Debug\ConsoleApplication1.pgd" /SUBSYSTEM:CONSOLE /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"Debug\ConsoleApplication1.exe.intermediate.manifest" /ERRORREPORT:PROMPT /NOLOGO /TLBID:1
'TerminateThread' is 'dangerous' and in fact some de-allocations may not occur (see https://learn.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-terminatethread). Best to redesign the code to cleanly exit threads without the use of 'TerminateThread'.
My problem is very simple and the title explains it all. Basically, when I compile my program with Visual Studio 2013, the dll injection works perfectly fine. When I compile the exact same program in Qt Creator, it doesn't.
I seem to have the same problem as this fellow: Why does Qt not work with dll injection?
Here is my code:
Injector.h
#ifndef INJECTOR_H_INCLUDED
#define INJECTOR_H_INCLUDED
#include <Windows.h>
#include <string>
class Injector
{
public:
/**
* Loads a DLL into the remote process
* #Return true on sucess, false on failure
*/
bool InjectDll(DWORD processId, std::string dllPath);
private:
};
#endif // INJECTOR_H_INCLUDED
Injector.cpp
#include "Injector.h"
bool Injector::InjectDll(DWORD processId, std::string dllPath)
{
HANDLE hThread, hProcess;
void* pLibRemote = 0; // the address (in the remote process) where szLibPath will be copied to;
HMODULE hKernel32 = GetModuleHandleA("Kernel32");
char DllFullPathName[_MAX_PATH];
GetFullPathNameA(dllPath.c_str(), _MAX_PATH, DllFullPathName, NULL);
printf("Loading dll: %s\n", DllFullPathName);
// Get process handle
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
// copy file path in szLibPath
char szLibPath[_MAX_PATH];
strcpy_s(szLibPath, DllFullPathName);
// 1. Allocate memory in the remote process for szLibPath
pLibRemote = VirtualAllocEx(hProcess, NULL, sizeof(szLibPath), MEM_COMMIT, PAGE_READWRITE);
if (pLibRemote == NULL)
{
printf("Couldn't allocate memory, please restart with administrator privileges\n");
return false;
}
// 2. Write szLibPath to the allocated memory
WriteProcessMemory(hProcess, pLibRemote, (void*)szLibPath, sizeof(szLibPath), NULL);
// 3. Force remote process to load dll
hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(hKernel32, "LoadLibraryA"), pLibRemote, 0, NULL);
if (hThread == NULL)
{
printf("Couldn't load DLL");
return false;
}
printf("Dll successfully loaded\n");
return true;
}
main.cpp
#include "injector.h"
int main(int argc, char *argv[])
{
Injector inject;
DWORD processId = 6224;
inject.InjectDll(processId, "MyDLL.dll");
system("pause");
}
And this is the DLL (I use the same DLL in both scenario, I don't recompile it):
#include <Windows.h>
#include <stdio.h>
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
AllocConsole();
freopen("CONOUT$", "w", stdout);
printf("base address: %X\n", (DWORD)GetModuleHandle(NULL));
break;
case DLL_PROCESS_DETACH:
FreeConsole();
}
return TRUE;
}
The program compiled in VS2013 correctly injects the dll, while the program compiled in Qt Creator says the dll injection was successful, yet the dll is never injected.
NOTE: The program I'm trying to inject is the same in both scenario and was NOT made with Qt.
Here are the compilers output:
Visual Studio:
cl /c /Zi /W3 /WX- /sdl /O2 /Oi /Oy- /GL /D _CRT_SECURE_NO_WARNINGS /D
_MBCS /Gm- /EHsc /MD /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Fo"Release\" /Fd"Release\vc120.pdb" /Gd /TP /analyze-
/errorReport:prompt Injector.cpp main.cpp
Qt:
C:\Qt\Qt5.4.0\Tools\QtCreator\bin\jom.exe -f Makefile.Release cl -c
-nologo -Zm200 -Zc:wchar_t -FS -O2 -MD -Zc:strictStrings -GR -W3 -w34100 -w34189 -EHsc -DUNICODE -DWIN32 -DWIN64 -DQT_NO_DEBUG -DQT_CORE_LIB -DNDEBUG -I"C:\Qt\Qt5.4.0\5.4\msvc2013_64_opengl\include" -I"C:\Qt\Qt5.4.0\5.4\msvc2013_64_opengl\include\QtCore" -I"release" -I"." -I"C:\Qt\Qt5.4.0\5.4\msvc2013_64_opengl\mkspecs\win32-msvc2013" -Forelease\ #C:\Users\JFG\AppData\Local\Temp\injector.obj.7040.0.jom injector.cpp link /NOLOGO /DYNAMICBASE /NXCOMPAT /INCREMENTAL:NO
/SUBSYSTEM:CONSOLE "/MANIFESTDEPENDENCY:type='win32'
name='Microsoft.Windows.Common-Controls' version='6.0.0.0'
publicKeyToken='6595b64144ccf1df' language=''
processorArchitecture=''" /MANIFEST:embed
/OUT:release\test_dll_inection_qt.exe
#C:\Users\JFG\AppData\Local\Temp\test_dll_inection_qt.exe.7040.469.jom
Any help would be appreciated, thank you.
The problem was that Qt compiled my program in 64bit while visual studio compiled it in 32bit.
I'm still not sure why injecting a 32bit dll in a 32bit target fails because of a 64bit injector, but for now I solved my problem...
This question already has answers here:
How to launch Windows' RegEdit with certain path?
(15 answers)
Closed 9 years ago.
I'm looking for way to open registry editor and show some specific key or value. For example, if I pass "HKLM\\SOFTWARE\\Skype\\Installer" I want to get such a result:
All suggestions except system() calls are welcome.
Just call system. To use Raymond Chen's words: It rather involved being on the other side of this airtight hatchway. Any relevant attack requires compromising the machine to the point that your system call is utterly irrelevant. In fact, any attacker that can change RegEdit can change your program as well, so he could just add that system call. (Which he won't, since it is pointless anyway)
Here is, what I needed.
String GetFullHKEY (HKEY hKeyRoot)
{
if (HKEY_LOCAL_MACHINE == hKeyRoot) return _T("HKEY_LOCAL_MACHINE\\");
if (HKEY_CLASSES_ROOT == hKeyRoot) return _T("HKEY_CLASSES_ROOT\\");
if (HKEY_CURRENT_CONFIG == hKeyRoot) return _T("HKEY_CURRENT_CONFIG\\");
if (HKEY_CURRENT_USER == hKeyRoot) return _T("HKEY_CURRENT_USER\\");
if (HKEY_USERS == hKeyRoot) return _T("HKEY_USERS\\");
}
bool RegistryGoTo (HKEY hKeyRoot, const String &lpctPath, String lpctValue)
{
if (lpctPath.empty() || 0 == hKeyRoot)
return false;
if( lpctValue.empty() && lpctValue.empty() == 0)
{
lpctValue.clear();
}
SHELLEXECUTEINFO shi = { 0 };
DEVMODE dm = { 0 };
HWND hWndRegedit = ::FindWindow (_T("RegEdit_RegEdit"), NULL);
if (NULL == hWndRegedit)
{
shi.cbSize = sizeof(SHELLEXECUTEINFO);
shi.fMask = SEE_MASK_NOCLOSEPROCESS;
shi.lpVerb = _T("open");
shi.lpFile = _T("regedit.exe");
shi.nShow = SW_SHOWNORMAL;
ShellExecuteEx (&shi);
if( GetLastError() != 0 )
{
Sleep(200);
ShellExecuteEx (&shi);
}
WaitForInputIdle (shi.hProcess, INFINITE);
hWndRegedit = ::FindWindow (_T("RegEdit_RegEdit"), NULL);
}
if (NULL == hWndRegedit) return FALSE;
SetForegroundWindow (hWndRegedit);
ShowWindow (hWndRegedit, SW_SHOWNORMAL);
HWND hWndTreeView = FindWindowEx (hWndRegedit, NULL, _T ("SysTreeView32"), NULL);
SetForegroundWindow (hWndTreeView);
SetFocus (hWndTreeView);
for (int i = 0; i < 30; i++)
{
SendMessage (hWndTreeView, WM_KEYDOWN, VK_LEFT, 0);
}
dm.dmSize = sizeof (DEVMODE);
EnumDisplaySettings (NULL, ENUM_CURRENT_SETTINGS, &dm);
if (8 < dm.dmBitsPerPel) Sleep (100);
// the path must start with a backslash
String stRegPath = String (_T("\\")) + GetFullHKEY(hKeyRoot) + lpctPath;
// open path
for (int iIndex = 0; iIndex < (int) stRegPath.length (); iIndex++)
{
if (_T('\\') == stRegPath [iIndex])
{
SendMessage (hWndTreeView, WM_KEYDOWN, VK_RIGHT, 0);
if (8 < dm.dmBitsPerPel)
Sleep (100);
}
else SendMessage (hWndTreeView, WM_CHAR, toupper (stRegPath [iIndex]), 0);
}
SetForegroundWindow (hWndRegedit);
SetFocus (hWndRegedit);
if (lpctValue.length())
{
HWND hWndListView = FindWindowEx (hWndRegedit, NULL, _T("SysListView32"), NULL);
SetForegroundWindow (hWndListView);
SetFocus (hWndListView);
Sleep (100);
SendMessage (hWndListView, WM_KEYDOWN, VK_HOME, 0);
String stValue = lpctValue;
for (String::iterator it = stValue.begin (); it != stValue.end (); ++it)
{
SendMessage (hWndListView, WM_CHAR, toupper (*it), 0);
}
}
return true;
}
How to get the OS version for all windows, at least the name for win95,98,me,xp,vista,7?
Im using visual c++ 2010 and I want to include this feature in a pure win32 app.
How about something like this:
#include <windows.h>
#include <string>
#include <lm.h>
#pragma comment(lib, "netapi32.lib")
bool GetWinMajorMinorVersion(DWORD& major, DWORD& minor)
{
bool bRetCode = false;
LPBYTE pinfoRawData = 0;
if (NERR_Success == NetWkstaGetInfo(NULL, 100, &pinfoRawData))
{
WKSTA_INFO_100* pworkstationInfo = (WKSTA_INFO_100*)pinfoRawData;
major = pworkstationInfo->wki100_ver_major;
minor = pworkstationInfo->wki100_ver_minor;
::NetApiBufferFree(pinfoRawData);
bRetCode = true;
}
return bRetCode;
}
std::string GetWindowsVersionString()
{
std::string winver;
OSVERSIONINFOEX osver;
SYSTEM_INFO sysInfo;
typedef void(__stdcall *GETSYSTEMINFO) (LPSYSTEM_INFO);
__pragma(warning(push))
__pragma(warning(disable:4996))
memset(&osver, 0, sizeof(osver));
osver.dwOSVersionInfoSize = sizeof(osver);
GetVersionEx((LPOSVERSIONINFO)&osver);
__pragma(warning(pop))
DWORD major = 0;
DWORD minor = 0;
if (GetWinMajorMinorVersion(major, minor))
{
osver.dwMajorVersion = major;
osver.dwMinorVersion = minor;
}
else if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 2)
{
OSVERSIONINFOEXW osvi;
ULONGLONG cm = 0;
cm = VerSetConditionMask(cm, VER_MINORVERSION, VER_EQUAL);
ZeroMemory(&osvi, sizeof(osvi));
osvi.dwOSVersionInfoSize = sizeof(osvi);
osvi.dwMinorVersion = 3;
if (VerifyVersionInfoW(&osvi, VER_MINORVERSION, cm))
{
osver.dwMinorVersion = 3;
}
}
GETSYSTEMINFO getSysInfo = (GETSYSTEMINFO)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "GetNativeSystemInfo");
if (getSysInfo == NULL) getSysInfo = ::GetSystemInfo;
getSysInfo(&sysInfo);
if (osver.dwMajorVersion == 10 && osver.dwMinorVersion >= 0 && osver.wProductType != VER_NT_WORKSTATION) winver = "Windows 10 Server";
if (osver.dwMajorVersion == 10 && osver.dwMinorVersion >= 0 && osver.wProductType == VER_NT_WORKSTATION) winver = "Windows 10";
if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 3 && osver.wProductType != VER_NT_WORKSTATION) winver = "Windows Server 2012 R2";
if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 3 && osver.wProductType == VER_NT_WORKSTATION) winver = "Windows 8.1";
if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 2 && osver.wProductType != VER_NT_WORKSTATION) winver = "Windows Server 2012";
if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 2 && osver.wProductType == VER_NT_WORKSTATION) winver = "Windows 8";
if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 1 && osver.wProductType != VER_NT_WORKSTATION) winver = "Windows Server 2008 R2";
if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 1 && osver.wProductType == VER_NT_WORKSTATION) winver = "Windows 7";
if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 0 && osver.wProductType != VER_NT_WORKSTATION) winver = "Windows Server 2008";
if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 0 && osver.wProductType == VER_NT_WORKSTATION) winver = "Windows Vista";
if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 2 && osver.wProductType == VER_NT_WORKSTATION
&& sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) winver = "Windows XP x64";
if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 2) winver = "Windows Server 2003";
if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 1) winver = "Windows XP";
if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 0) winver = "Windows 2000";
if (osver.dwMajorVersion < 5) winver = "unknown";
if (osver.wServicePackMajor != 0)
{
std::string sp;
char buf[128] = { 0 };
sp = " Service Pack ";
sprintf_s(buf, sizeof(buf), "%hd", osver.wServicePackMajor);
sp.append(buf);
winver += sp;
}
return winver;
}
Use GetVersionEx
http://msdn.microsoft.com/en-us/library/ms724451%28v=VS.85%29.aspx
I had a similar problem. Here is some code with Win 11 support. It won't work for server versions, but it is easy to implement add this feature (just another mapping for servers).
// To Workaround Win 10 problem for User Mode VerifyVersionInfo
bool VerifyWindowsVersionInfo(PRTL_OSVERSIONINFOEXW versionInfo, ULONG typeMask, ULONGLONG conditionMask)
{
HMODULE hMod = nullptr;
if ((TRUE != ::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, L"ntdll.dll", &hMod)) || !hMod)
return false;
typedef NTSTATUS(WINAPI* _RtlVerifyVersionInfo)(PRTL_OSVERSIONINFOEXW, ULONG, ULONGLONG);
const auto RtlVerifyVersionInfo =
reinterpret_cast<_RtlVerifyVersionInfo>(::GetProcAddress(hMod, "RtlVerifyVersionInfo"));
if (!RtlVerifyVersionInfo)
return false;
return NT_SUCCESS(RtlVerifyVersionInfo(versionInfo, typeMask, conditionMask));
}
bool IsWindowsVersionOrGreater(int wMajorVersion, int wMinorVersion, int wBuildNumber, int wServicePackMajor)
{
RTL_OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0 };
osvi.dwMajorVersion = wMajorVersion;
osvi.dwMinorVersion = wMinorVersion;
osvi.dwBuildNumber = wBuildNumber;
osvi.wServicePackMajor = static_cast<WORD>(wServicePackMajor);
DWORDLONG dwlConditionMask = 0;
VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
VER_SET_CONDITION(dwlConditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL);
VER_SET_CONDITION(dwlConditionMask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
return VerifyWindowsVersionInfo(&osvi,
VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER | VER_SERVICEPACKMAJOR,
dwlConditionMask);
}
std::wstring GetVerbalOsVersion()
{
// see https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms724832(v=vs.85).aspx for details
using OsMajorVersion = int;
using OsMinorVersion = int;
using OsBuildVersion = int;
using OsServicePackMajorVersion = int;
using VersionStrWithNumberPair =
std::pair<std::wstring, std::tuple<OsMajorVersion, OsMinorVersion, OsBuildVersion, OsServicePackMajorVersion>>;
const auto win11BuildNumber = 22000;
const std::vector<VersionStrWithNumberPair> winVersionMapping = {
{L"Windows 11 ",
std::make_tuple(HIBYTE(_WIN32_WINNT_WIN10), LOBYTE(_WIN32_WINNT_WIN10), win11BuildNumber, 0)},
{L"Windows 10 ", std::make_tuple(HIBYTE(_WIN32_WINNT_WIN10), LOBYTE(_WIN32_WINNT_WIN10), 0, 0)},
{L"Windows 8.1", std::make_tuple(HIBYTE(_WIN32_WINNT_WINBLUE), LOBYTE(_WIN32_WINNT_WINBLUE), 0, 0)},
{L"Windows 8 ", std::make_tuple(HIBYTE(_WIN32_WINNT_WIN8), LOBYTE(_WIN32_WINNT_WIN8), 0, 0)},
{L"Windows 7 Service Pack 1", std::make_tuple(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 0, 1)},
{L"Windows 7 ", std::make_tuple(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 0, 0)},
{L"Windows Vista Service Pack 2",
std::make_tuple(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0, 2)},
{L"Windows Vista Service Pack 1",
std::make_tuple(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0, 1)},
{L"Windows Vista", std::make_tuple(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0, 0)},
{L"Windows XP Service Pack 3",
std::make_tuple(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0, 3)},
{L"Windows XP Service Pack 2",
std::make_tuple(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0, 2)},
{L"Windows XP Service Pack 1",
std::make_tuple(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0, 1)},
{L"Windows XP ", std::make_tuple(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0, 0)} };
const auto it = std::find_if(std::begin(winVersionMapping),
std::end(winVersionMapping),
[](const VersionStrWithNumberPair& el)
{
return IsWindowsVersionOrGreater(std::get<0>(el.second),
std::get<1>(el.second),
std::get<2>(el.second),
std::get<3>(el.second));
});
if (it == std::end(winVersionMapping))
return L"Unknown windows version";
return it->first;
}
Take a look at the MSDN article Getting the System Version
While the article only mentions currently supported Windows versions, see this knowledge base article for the numbers you'll see in the OSVERSIONINFO structure for Win 95, 98 etc.
It all depends on why you need to know OS version:
To use certain feature that may not be available in older OS. In this case I would strongly suggest checking if the API itself is available using LoadLibrary and GetProcAddress functions. Otherwise, I guess you can dynamically import RtlGetVersion from ntdll.dll and use it, but again, there're too many ways it can return inaccurate information (the ones that come to mind are compatibility mode and API trampolines that can be installed by malware, AVP, and even OS itself.)
For display purposes only. (ex: in About window for your app, or to include it in your diagnostic event log, etc.) In this case a quick and easy hack is to read it as text from the System Registry:
The downside of this approach though, is that the names and numbers can be localized for the end-user's system.
Use the following key that is available since Windows XP:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
and its following REG_SZ (or string) values:
ProductName = for OS name
CurrentVersion = for OS version
BuildLab = for full build number
BuildLabEx = extended build number (available since Windows 7)
ReleaseId = Release number (available since Windows 10)
I have this code here:
#include "windows.h"
#include "Tlhelp32.h"
#include "shellapi.h"
#include <wchar.h>
#include <fstream>
bool enumProcesses();
int main()
{
enumProcesses();
ShellExecute( NULL, L"open", L"log.txt", NULL, NULL, SW_SHOW );
return 0;
}
bool enumProcesses()
{
std::wofstream log("log.txt");
PROCESSENTRY32 lppe;
MODULEENTRY32 lpme;
HANDLE hSnapshot;
HANDLE mSnapshot;
lppe.dwSize = sizeof( PROCESSENTRY32 );
lpme.dwSize = sizeof( MODULEENTRY32 );
hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if( hSnapshot == INVALID_HANDLE_VALUE )
{
log << L"Error creating process snapshot.";
return false;
}
if( !Process32First( hSnapshot, &lppe ) )
{
log << L"Error enumerating first process.";
return false;
}
else
{
mSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, lppe.th32ProcessID );
if( mSnapshot != INVALID_HANDLE_VALUE )
{
Module32First( mSnapshot, &lpme );
}
if( wcscmp( lppe.szExeFile, L"[System Process]" ) != 0 )
{
log << lpme.szExePath << "\n";
}
}
while( Process32Next( hSnapshot, &lppe ) )
{
if( wcscmp( lppe.szExeFile, L"System" ) != 0 )
{
if( (mSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, lppe.th32ProcessID )) != INVALID_HANDLE_VALUE )
{
if( Module32First( mSnapshot, &lpme ) ) {
log << lpme.szExePath << "\n";
}
}
}
}
CloseHandle( hSnapshot );
CloseHandle( mSnapshot );
log.close();
return true;
}
My problem is that whenever I debug this code in VC++ using F5 or CTRL + F5, it shows me all the processes but when I create a release version and run it, some things don't even show anymore and I'm not sure why..
Here's what I'm talking about:
release version:
C:\WINDOWS\Explorer.EXE
C:\Program Files\Java\jre6\bin\jusched.exe
C:\WINDOWS\system32\ctfmon.exe
C:\Program Files\Messenger\msmsgs.exe
C:\WINDOWS\system32\wscntfy.exe
C:\WINDOWS\system32\wuauclt.exe
c:\Program Files\Microsoft Visual Studio 9.0\Common7\ide\mspdbsrv.exe
C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe
C:\Program Files\Mozilla Firefox\firefox.exe
C:\Documents and Settings\windows\Desktop\c++ projects\gggg\Debug\gggg.exe
log created on debug:
\SystemRoot\System32\smss.exe
\??\C:\WINDOWS\system32\csrss.exe
\??\C:\WINDOWS\system32\winlogon.exe
C:\WINDOWS\system32\services.exe
C:\WINDOWS\system32\lsass.exe
C:\WINDOWS\system32\svchost.exe
C:\WINDOWS\system32\svchost.exe
C:\WINDOWS\System32\svchost.exe
C:\WINDOWS\system32\svchost.exe
C:\WINDOWS\system32\svchost.exe
C:\WINDOWS\system32\spoolsv.exe
C:\WINDOWS\Explorer.EXE
C:\Program Files\Java\jre6\bin\jusched.exe
C:\WINDOWS\system32\ctfmon.exe
C:\Program Files\Messenger\msmsgs.exe
C:\Program Files\Java\jre6\bin\jqs.exe
c:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Binn\sqlservr.exe
c:\Program Files\Microsoft SQL Server\90\Shared\sqlwriter.exe
C:\WINDOWS\System32\alg.exe
C:\WINDOWS\system32\wscntfy.exe
C:\WINDOWS\system32\wuauclt.exe
c:\Program Files\Microsoft Visual Studio 9.0\Common7\ide\mspdbsrv.exe
C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe
C:\Program Files\Mozilla Firefox\firefox.exe
C:\WINDOWS\system32\NOTEPAD.EXE
C:\WINDOWS\system32\cmd.exe
c:\Documents and Settings\windows\Desktop\c++ projects\gggg\Release\gggg.exe
Does it have something to do with permissions?
EDIT:
Looking at 1800 INFORMATION's post, I tried to "force" it to run under SYSTEM account by using psexec -i -d -s and it worked... Is there any way I could run this without the need of doing such a thing?
I bet that when you debug it, you are running it from within Visual Studio with administrator privileges, while when you run the release build, it does not so it will not be able to see all of the processes in the system. This is the same reason that task manager cannot list all of the running processes unless you elevate.