I'd like to use the function QueryWorkingSet available in PSAPI, but I'm having trouble to actually define the size of the buffer pv. Here is the code :
#include <Windows.h>
#include <Psapi.h>
#include <iostream>
void testQueryWorkingSet()
{
unsigned int counter;
HANDLE thisProcess = GetCurrentProcess();
SYSTEM_INFO si;
PSAPI_WORKING_SET_INFORMATION wsi, wsi2;
GetSystemInfo(&si);
QueryWorkingSet(thisProcess, &wsi, sizeof(wsi));
DWORD wsi2_buffer_size = (wsi.NumberOfEntries) * sizeof(PSAPI_WORKING_SET_BLOCK);
if (!QueryWorkingSet(thisProcess, &wsi2, wsi2_buffer_size))
{
std::cout << "ERROR CODE : " << GetLastError() << std::endl;
abort();
}
}
int main(int argc, char * argv[])
{
testQueryWorkingSet();
int* test = new int[1000000];
testQueryWorkingSet();
}
I keep ending up with abort() being called and either an error code 24 or 998 during the first call to testQueryWorkingSet(). that I interpret respectively as : wsi2_buffer_size is too low and wsi2_buffer_size is too big.
Now I have no idea of the value this variable should take, I tried :
- counting everything including the
NumberOfEntriesfield, that isDWORD wsi2_buffer_size = sizeof(wsi.NumberOfEntries) + wsi.NumberOfEntries * sizeof(PSAPI_WORKING_SET_BLOCK);=> error 998; - counting only the number of entries, that is the code given above => error 998;
- the size of the variable wsi2, that is
DWORD wsi2_buffer_size = sizeof(wsi2);=> error 24;
There has to be something I do not understand in the way we're supposed to use this function but I can't find what. I tried to adapt the code given there, that is :
#include <Windows.h>
#include <Psapi.h>
#include <iostream>
void testQueryWorkingSet()
{
unsigned int counter;
HANDLE thisProcess = GetCurrentProcess();
SYSTEM_INFO si;
PSAPI_WORKING_SET_INFORMATION wsi_1, * wsi;
DWORD wsi_size;
GetSystemInfo(&si);
wsi_1.NumberOfEntries = 0;
QueryWorkingSet(thisProcess, (LPVOID)&wsi_1, sizeof(wsi));
#if !defined(_WIN64)
wsi_1.NumberOfEntries--;
#endif
wsi_size = sizeof(PSAPI_WORKING_SET_INFORMATION)
+ sizeof(PSAPI_WORKING_SET_BLOCK) * wsi_1.NumberOfEntries;
wsi = (PSAPI_WORKING_SET_INFORMATION*)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, wsi_size);
if (!QueryWorkingSet(thisProcess, (LPVOID)wsi, wsi_size)) {
printf("# Second QueryWorkingSet failed: %lu\n"
, GetLastError());
abort();
}
}
int main(int argc, char * argv[])
{
testQueryWorkingSet();
int* test = new int[1000000];
testQueryWorkingSet();
}
This code is working for only 1 call to testQueryWorkingSet(), the second one is aborting with error code 24. Here are the questions in brief :
- How would you use
QueryWorkingSetin a function that you could call multiple times successively? - What is representing the value of the parameter
cbof the documentation given aPSAPI_WORKING_SET_INFORMATION?
Both examples are completely ignoring the return value and error code of the 1st call of
QueryWorkingSet(). You are doing error handling only on the 2nd call.Your 1st example fails because you are not taking into account the entire size of the
PSAPI_WORKING_SET_INFORMATIONwhen calculatingwsi2_buffer_sizefor the 2nd call ofQueryWorkingSet(). Even if the 1st call were successful, you are not allocating any additional memory for the 2nd call to fill in, if theNumberOfEntriesreturned is > 1.Your 2nd example is passing in the wrong buffer size value to the
cbparameter of the 1st call ofQueryWorkingSet(). You are passing in just the size of a single pointer, not the size of the entirePSAPI_WORKING_SET_INFORMATION. Error 24 isERROR_BAD_LENGTH. You need to usesizeof(wsi_1)instead ofsizeof(wsi).I would suggest calling
QueryWorkingSet()in a loop, in case the working set actually changes in between the call to query its size and the call to get its data.Also, be sure you free the memory you allocate when you are done using it.
With that said, try something more life this: