Why WINAPI works differently in Qt
-
NOTE: pls don't be afraid of such 'huge' examples. It's actually very simple, if you'll copy and paste in your empty app it will work as it should.
I spent so much time to understand what's wrong, and why in Qt results are incomplete, but the fact - it is.
Here is an example from MSVC documentation about how to print all modules of the selected program(sorry can't use spoiler feature because there is none):
#include "stdafx.h" #include <Windows.h> #include <Psapi.h> #include <iostream> #include <string> using namespace std; void printModules(DWORD id) { HMODULE modArr[1024]; unsigned int tital = 0; DWORD cbNeeded = 0; HANDLE someHandle = OpenProcess(PROCESS_ALL_ACCESS, false, id); if(someHandle != NULL) { if(EnumProcessModules(someHandle, modArr, sizeof(modArr), &cbNeeded)) { tital = cbNeeded / sizeof(HMODULE); cout << "Modules: " << tital << endl << endl; for(int i = 0; i < tital; i++) { char tempSTR[32]; if(GetModuleBaseNameA(someHandle, modArr[i], tempSTR, sizeof(tempSTR))) { cout << i + 1 << ": " << tempSTR << endl; MODULEINFO infoVar; if(GetModuleInformation(someHandle, modArr[i], &infoVar, sizeof(infoVar)) != 0) { cout << infoVar.EntryPoint << endl; cout << infoVar.SizeOfImage << endl; } else { cout << "FAIL-0" << endl; } } } } else { cout << "FAIL-1" << endl; } } else { cout << "FAIL-2" << endl; } CloseHandle(someHandle); }
This function will work perfectly in VS if you'll just copy it and use instantly. And here take a look for it's absolute copy in Qt:
#include <Windows.h> #include <Psapi.h> void MWindow::printModules(DWORD id) { HMODULE modArr[1024]; unsigned int tital = 0; DWORD cbNeeded = 0; HANDLE someHandle = OpenProcess(PROCESS_ALL_ACCESS, false, id); if(someHandle != NULL) { if(EnumProcessModules(someHandle, modArr, sizeof(modArr), &cbNeeded)) { tital = cbNeeded / sizeof(HMODULE); ui->textBrowser1->append("Moduels: "); ui->textBrowser1->append(" "); for(int i = 0; i < tital; i++) { char tempSTR[32]; if(GetModuleBaseNameA(someHandle, modArr[i], tempSTR, sizeof(tempSTR))) { ui->textBrowser1->append(QString::number(i+1)+": "+QString::fromLatin1(tempSTR)); MODULEINFO infoVar; if(GetModuleInformation(someHandle, modArr[i], &infoVar, sizeof(infoVar)) != 0) { ui->textBrowser1->append( QString::number(reinterpret_cast<DWORD>(infoVar.EntryPoint))); ui->textBrowser1->append( QString::number(infoVar.SizeOfImage)); } else { ui->textBrowser1->append("FAIL-0"); } } } } else { ui->textBrowser1->append("FAIL-1"); } } else { ui->textBrowser1->append("FAIL-2"); } CloseHandle(someHandle); }
Well it does print correct for some process like Windows stuff "Explorer.exe", but for the most, it print only 5 modules, even when huge process(like a game) where is VS shows 170 modules, Qt shows 5. For example my small VS console TEST.exe application have 7 modules, in Qt it displays 5, and most of them(module names and entrypoints/size's) are differ from those which show me VS version.
What wrong, and why in Qt same code gives different(wrong) results? How can i fix this?
P.S. yes, there was similar topic from me like 2 month's ago, but there was 0 answers, and for the now it's absolutely important.
-
Damn i found it!
There is one more function in WinApi with postfix Ex: EnumProcessModulesEx. As it said in documentation of first function(which in my example):
To control whether a 64-bit application enumerates 32-bit modules, 64-bit modules, or both types of modules, use the EnumProcessModulesEx function.
All was needed is add Ex to that function and one more parameter at the end LIST_MODULES_ALL
-
NOTE: pls don't be afraid of such 'huge' examples. It's actually very simple, if you'll copy and paste in your empty app it will work as it should.
I spent so much time to understand what's wrong, and why in Qt results are incomplete, but the fact - it is.
Here is an example from MSVC documentation about how to print all modules of the selected program(sorry can't use spoiler feature because there is none):
#include "stdafx.h" #include <Windows.h> #include <Psapi.h> #include <iostream> #include <string> using namespace std; void printModules(DWORD id) { HMODULE modArr[1024]; unsigned int tital = 0; DWORD cbNeeded = 0; HANDLE someHandle = OpenProcess(PROCESS_ALL_ACCESS, false, id); if(someHandle != NULL) { if(EnumProcessModules(someHandle, modArr, sizeof(modArr), &cbNeeded)) { tital = cbNeeded / sizeof(HMODULE); cout << "Modules: " << tital << endl << endl; for(int i = 0; i < tital; i++) { char tempSTR[32]; if(GetModuleBaseNameA(someHandle, modArr[i], tempSTR, sizeof(tempSTR))) { cout << i + 1 << ": " << tempSTR << endl; MODULEINFO infoVar; if(GetModuleInformation(someHandle, modArr[i], &infoVar, sizeof(infoVar)) != 0) { cout << infoVar.EntryPoint << endl; cout << infoVar.SizeOfImage << endl; } else { cout << "FAIL-0" << endl; } } } } else { cout << "FAIL-1" << endl; } } else { cout << "FAIL-2" << endl; } CloseHandle(someHandle); }
This function will work perfectly in VS if you'll just copy it and use instantly. And here take a look for it's absolute copy in Qt:
#include <Windows.h> #include <Psapi.h> void MWindow::printModules(DWORD id) { HMODULE modArr[1024]; unsigned int tital = 0; DWORD cbNeeded = 0; HANDLE someHandle = OpenProcess(PROCESS_ALL_ACCESS, false, id); if(someHandle != NULL) { if(EnumProcessModules(someHandle, modArr, sizeof(modArr), &cbNeeded)) { tital = cbNeeded / sizeof(HMODULE); ui->textBrowser1->append("Moduels: "); ui->textBrowser1->append(" "); for(int i = 0; i < tital; i++) { char tempSTR[32]; if(GetModuleBaseNameA(someHandle, modArr[i], tempSTR, sizeof(tempSTR))) { ui->textBrowser1->append(QString::number(i+1)+": "+QString::fromLatin1(tempSTR)); MODULEINFO infoVar; if(GetModuleInformation(someHandle, modArr[i], &infoVar, sizeof(infoVar)) != 0) { ui->textBrowser1->append( QString::number(reinterpret_cast<DWORD>(infoVar.EntryPoint))); ui->textBrowser1->append( QString::number(infoVar.SizeOfImage)); } else { ui->textBrowser1->append("FAIL-0"); } } } } else { ui->textBrowser1->append("FAIL-1"); } } else { ui->textBrowser1->append("FAIL-2"); } CloseHandle(someHandle); }
Well it does print correct for some process like Windows stuff "Explorer.exe", but for the most, it print only 5 modules, even when huge process(like a game) where is VS shows 170 modules, Qt shows 5. For example my small VS console TEST.exe application have 7 modules, in Qt it displays 5, and most of them(module names and entrypoints/size's) are differ from those which show me VS version.
What wrong, and why in Qt same code gives different(wrong) results? How can i fix this?
P.S. yes, there was similar topic from me like 2 month's ago, but there was 0 answers, and for the now it's absolutely important.
@Engelard said in Why WINAPI works differently in Qt:
Qt shows 5
What compiler do you use for your Qt project?
-
@Engelard said in Why WINAPI works differently in Qt:
Qt shows 5
What compiler do you use for your Qt project?
Ok, i got it.
- How can i find out place where compiler of my VS2017 stored?
- How would i change current compiler of my Qt in to that which from VS
Because i tried in Kits change current compiler, but there is still that one which on screenshot above.
-
NOTE: pls don't be afraid of such 'huge' examples. It's actually very simple, if you'll copy and paste in your empty app it will work as it should.
I spent so much time to understand what's wrong, and why in Qt results are incomplete, but the fact - it is.
Here is an example from MSVC documentation about how to print all modules of the selected program(sorry can't use spoiler feature because there is none):
#include "stdafx.h" #include <Windows.h> #include <Psapi.h> #include <iostream> #include <string> using namespace std; void printModules(DWORD id) { HMODULE modArr[1024]; unsigned int tital = 0; DWORD cbNeeded = 0; HANDLE someHandle = OpenProcess(PROCESS_ALL_ACCESS, false, id); if(someHandle != NULL) { if(EnumProcessModules(someHandle, modArr, sizeof(modArr), &cbNeeded)) { tital = cbNeeded / sizeof(HMODULE); cout << "Modules: " << tital << endl << endl; for(int i = 0; i < tital; i++) { char tempSTR[32]; if(GetModuleBaseNameA(someHandle, modArr[i], tempSTR, sizeof(tempSTR))) { cout << i + 1 << ": " << tempSTR << endl; MODULEINFO infoVar; if(GetModuleInformation(someHandle, modArr[i], &infoVar, sizeof(infoVar)) != 0) { cout << infoVar.EntryPoint << endl; cout << infoVar.SizeOfImage << endl; } else { cout << "FAIL-0" << endl; } } } } else { cout << "FAIL-1" << endl; } } else { cout << "FAIL-2" << endl; } CloseHandle(someHandle); }
This function will work perfectly in VS if you'll just copy it and use instantly. And here take a look for it's absolute copy in Qt:
#include <Windows.h> #include <Psapi.h> void MWindow::printModules(DWORD id) { HMODULE modArr[1024]; unsigned int tital = 0; DWORD cbNeeded = 0; HANDLE someHandle = OpenProcess(PROCESS_ALL_ACCESS, false, id); if(someHandle != NULL) { if(EnumProcessModules(someHandle, modArr, sizeof(modArr), &cbNeeded)) { tital = cbNeeded / sizeof(HMODULE); ui->textBrowser1->append("Moduels: "); ui->textBrowser1->append(" "); for(int i = 0; i < tital; i++) { char tempSTR[32]; if(GetModuleBaseNameA(someHandle, modArr[i], tempSTR, sizeof(tempSTR))) { ui->textBrowser1->append(QString::number(i+1)+": "+QString::fromLatin1(tempSTR)); MODULEINFO infoVar; if(GetModuleInformation(someHandle, modArr[i], &infoVar, sizeof(infoVar)) != 0) { ui->textBrowser1->append( QString::number(reinterpret_cast<DWORD>(infoVar.EntryPoint))); ui->textBrowser1->append( QString::number(infoVar.SizeOfImage)); } else { ui->textBrowser1->append("FAIL-0"); } } } } else { ui->textBrowser1->append("FAIL-1"); } } else { ui->textBrowser1->append("FAIL-2"); } CloseHandle(someHandle); }
Well it does print correct for some process like Windows stuff "Explorer.exe", but for the most, it print only 5 modules, even when huge process(like a game) where is VS shows 170 modules, Qt shows 5. For example my small VS console TEST.exe application have 7 modules, in Qt it displays 5, and most of them(module names and entrypoints/size's) are differ from those which show me VS version.
What wrong, and why in Qt same code gives different(wrong) results? How can i fix this?
P.S. yes, there was similar topic from me like 2 month's ago, but there was 0 answers, and for the now it's absolutely important.
@Engelard said in Why WINAPI works differently in Qt:
One observation. The code you have copied is very misleading.
if(cnt = GetModuleBaseNameA(someHandle, modArr[i], tempSTR, sizeof(tempSTR)) != 0)
Although this will "work", given the rest of the code as written in the example you copied from, it is very misleading. The poster of that almost certainly got his parenthesization wrong for what he intended to do here with the value of
cnt
(which fortunately he does not use again after setting it like this). Just a heads-up for you/anyone else reading.Now to your issue. What do you mean by "VS shows" vs "in Qt"? VS is an IDE. Qt is a library of functions. It's not a compiler, nor a language.
So far as I can spot, the only difference is how you print out the information, right? So all all that actually matters is what is returned by
tital = cbNeeded / sizeof(HMODULE);
, as that determines how many items there are to report on, which you say differs.P.S.
You have now answered @jsulm that you are using a 64-bit MSVC compiler from Qt Creator. Are you using the same compiler in your VS2017, in particular 64-bit not 32-bit? Because if they differ by bit-ness, I suspect we're looking for something to do with that (e.g. I'm looking at you,tital = cbNeeded / sizeof(HMODULE);
, or we're looking at a member layout/alignment problem especially from your output being "different" ...). -
Ok, i got it.
- How can i find out place where compiler of my VS2017 stored?
- How would i change current compiler of my Qt in to that which from VS
Because i tried in Kits change current compiler, but there is still that one which on screenshot above.
@Engelard The location of the compiler can be seen where Kits are defined (Compiler tab). But you're already using MSVC2017 compiler - do you use same compiler in VS? Also, you're using Win API, could be that you need to pass some special parameters to compiler (you can compare compiler calls when building in VS and in QtCreator).
If you want to use Qt with different compiler you first need to install Qt for that compiler. -
@Engelard said in Why WINAPI works differently in Qt:
One observation. The code you have copied is very misleading.
if(cnt = GetModuleBaseNameA(someHandle, modArr[i], tempSTR, sizeof(tempSTR)) != 0)
Although this will "work", given the rest of the code as written in the example you copied from, it is very misleading. The poster of that almost certainly got his parenthesization wrong for what he intended to do here with the value of
cnt
(which fortunately he does not use again after setting it like this). Just a heads-up for you/anyone else reading.Now to your issue. What do you mean by "VS shows" vs "in Qt"? VS is an IDE. Qt is a library of functions. It's not a compiler, nor a language.
So far as I can spot, the only difference is how you print out the information, right? So all all that actually matters is what is returned by
tital = cbNeeded / sizeof(HMODULE);
, as that determines how many items there are to report on, which you say differs.P.S.
You have now answered @jsulm that you are using a 64-bit MSVC compiler from Qt Creator. Are you using the same compiler in your VS2017, in particular 64-bit not 32-bit? Because if they differ by bit-ness, I suspect we're looking for something to do with that (e.g. I'm looking at you,tital = cbNeeded / sizeof(HMODULE);
, or we're looking at a member layout/alignment problem especially from your output being "different" ...).@JonB said in Why WINAPI works differently in Qt:
So all all that actually matters is what is returned by tital = cbNeeded / sizeof(HMODULE);, as that determines how many items there are to report on, which you say differs.
Nope. I changed it manually for example to 10, it still print same 5 modules but twice
@JonB said in Why WINAPI works differently in Qt:
One observation. The code you have copied is very misleading.
removed
-
@Engelard The location of the compiler can be seen where Kits are defined (Compiler tab). But you're already using MSVC2017 compiler - do you use same compiler in VS? Also, you're using Win API, could be that you need to pass some special parameters to compiler (you can compare compiler calls when building in VS and in QtCreator).
If you want to use Qt with different compiler you first need to install Qt for that compiler. -
@jsulm I told you i know where compiler settings are. I've already tried to set another compiler in my Qt but it did'nt workout for some reason.
And i just can't find info in VS what compiler i use, also no info in google, or i entering wrong answer.
@Engelard said in Why WINAPI works differently in Qt:
it did'nt workout for some reason
I explained you what you need to do.
"How can i find out place where compiler of my VS2017 stored?" - that's why I suggested to look at "Compilers" tab in QtCreator - it will show you where the compiler is. Wasn't that the question you asked?
-
@Engelard said in Why WINAPI works differently in Qt:
it did'nt workout for some reason
I explained you what you need to do.
"How can i find out place where compiler of my VS2017 stored?" - that's why I suggested to look at "Compilers" tab in QtCreator - it will show you where the compiler is. Wasn't that the question you asked?
@jsulm said in Why WINAPI works differently in Qt:
I suggested to look at "Compilers" tab in QtCreator - it will show you where the compiler is. Wasn't that the question you asked?
In that tab like 30 compilers. I asked for location of used compiler by VS, why would Qt know what my VS using?
P.S. here is screen of my Kits where everything:
-
@jsulm said in Why WINAPI works differently in Qt:
I suggested to look at "Compilers" tab in QtCreator - it will show you where the compiler is. Wasn't that the question you asked?
In that tab like 30 compilers. I asked for location of used compiler by VS, why would Qt know what my VS using?
P.S. here is screen of my Kits where everything:
-
@Engelard Then please formulate more clear questions.
"How can i find out place where compiler of my VS2017 stored?" - this asks for the location of your VS compiler, not for the compiler currently used in VS... -
@jsulm "And i just can't find info in VS what compiler i use"
Anyway where can i look in Visual Studio for info about compiler currently this IDE using?
@Engelard
As well as sorting out what compilers you are using with @jsulm (which you definitely need to do):In the two sets of code, print/debug out at least the following values as you use them:
sizeof(HMODULE) sizeof(modArr) cbNeeded sizeof(tempSTR) sizeof(infoVar)
Any differences?
Also: to a C++ expert:
He useschar tempSTR[32]; GetModuleBaseNameA(someHandle, modArr[i], tempSTR, sizeof(tempSTR))
Is the use of
char
withGetModuleBaseNameA
OK? Does it depend onUNICODE
orsizeof(char)
or something? Should thechar
be anything likew_char
orTCHAR
or similar, or theGetModuleBaseNameA()
beGetModuleBaseNameW()
or plainGetModuleBaseName()
? Not my area.... -
@Engelard
As well as sorting out what compilers you are using with @jsulm (which you definitely need to do):In the two sets of code, print/debug out at least the following values as you use them:
sizeof(HMODULE) sizeof(modArr) cbNeeded sizeof(tempSTR) sizeof(infoVar)
Any differences?
Also: to a C++ expert:
He useschar tempSTR[32]; GetModuleBaseNameA(someHandle, modArr[i], tempSTR, sizeof(tempSTR))
Is the use of
char
withGetModuleBaseNameA
OK? Does it depend onUNICODE
orsizeof(char)
or something? Should thechar
be anything likew_char
orTCHAR
or similar, or theGetModuleBaseNameA()
beGetModuleBaseNameW()
or plainGetModuleBaseName()
? Not my area....@JonB It is LPSTR according to https://docs.microsoft.com/en-us/windows/desktop/api/psapi/nf-psapi-getmodulebasenamea which in turn is char* according to https://msdn.microsoft.com/en-us/library/cc230353.aspx
-
@Engelard
As well as sorting out what compilers you are using with @jsulm (which you definitely need to do):In the two sets of code, print/debug out at least the following values as you use them:
sizeof(HMODULE) sizeof(modArr) cbNeeded sizeof(tempSTR) sizeof(infoVar)
Any differences?
Also: to a C++ expert:
He useschar tempSTR[32]; GetModuleBaseNameA(someHandle, modArr[i], tempSTR, sizeof(tempSTR))
Is the use of
char
withGetModuleBaseNameA
OK? Does it depend onUNICODE
orsizeof(char)
or something? Should thechar
be anything likew_char
orTCHAR
or similar, or theGetModuleBaseNameA()
beGetModuleBaseNameW()
or plainGetModuleBaseName()
? Not my area.... -
@JonB It is LPSTR according to https://docs.microsoft.com/en-us/windows/desktop/api/psapi/nf-psapi-getmodulebasenamea which in turn is char* according to https://msdn.microsoft.com/en-us/library/cc230353.aspx
@jsulm
This isn't my area, so you C++-ers must sort it out! But that doc link says stuff like:nSize
The size of the lpBaseName buffer, in characters.That's characters, not bytes. And
sizeof()
returns, bytes, right? And he might be compilingUNICODE
, right? Can I leave this all to you guys, if you're happy that's fine, it was just an observation.... -
@JonB No, all that stuff with char's does'nt matter because 'tital' number is wrong, and displaying of all that stuff after with simple char array works well.
-
because 'tital' number is wrong
As I said above, I think you should print out the relevant
sizeof()
s used to calculate that.... -
@Engelard said in Why WINAPI works differently in Qt:
Vs print that is 28(for my test app), when qt print 40.
That's what one would expect since when you link against Qt your app needs more modules.
-
Damn i found it!
There is one more function in WinApi with postfix Ex: EnumProcessModulesEx. As it said in documentation of first function(which in my example):
To control whether a 64-bit application enumerates 32-bit modules, 64-bit modules, or both types of modules, use the EnumProcessModulesEx function.
All was needed is add Ex to that function and one more parameter at the end LIST_MODULES_ALL
-
@Engelard said in Why WINAPI works differently in Qt:
Vs print that is 28(for my test app), when qt print 40.
That's what one would expect since when you link against Qt your app needs more modules.
@Christian-Ehrlicher
From OP'show to print all modules of the selected program
void MWindow::printModules(DWORD id)
I assumed he was passing the
id
of another program's modules, not the one he is running! Just shows...