Segmentation Error on EnumMonitors WinAPI

I am writing code to check if my virtual printer is installed, for this I use winapi EnumMonitors, compiling the code, but when I try to run my program, it crashes. Debugging my program, I received a segmentation failure error on this line: EnumMonitors(NULL, 0, (LPBYTE)buffer, sizeof(buffer), &capacity, &returned); In the .pro file, I added LIBS += "C:\Program Files\Microsoft SDKs\Windows\v7.1\Lib\WinSpool.Lib" What can I do to get EnumMonitors WinAPI to work?

My code is:

 #include <windows.h> #include <winspool.h> void Enum() { char buffer[4096]; DWORD capacity; DWORD returned; QString monitorname = "Redirected Port"; /*Program crashes here*/ EnumMonitors(NULL, 1, (LPBYTE)buffer, sizeof(buffer), &capacity, &returned); MONITOR_INFO_1 *mi = (MONITOR_INFO_1*)buffer; for (uint i = 0; i < returned; i++) { if (QString::fromWCharArray(mi[i].pName) == monitorname) { //Do something } } } 

Edit: I updated the code from 0 to 1 as the second argument

+4
source share
3 answers

Which compiler are you using? When I try to execute the code as is in C ++ Builder, EnumMonitors() does not crash and returns an ERROR_INVALID_LEVEL error as expected. This makes me think that perhaps your compiler is not declaring EnumMonitors() correctly, for example, by improperly managing the call stack.

+2
source

The following commented code seems to work with VS2010 SP1 (VC10).

Follow the comments on how to call the EnumMonitors() API.

Basically, the first time you call the size of the output buffer, call EnumMonitors() with cbBuf equal to zero.

Then you correctly size std::vector with the correct size of the output buffer and pass the address of the first byte in the vector (using std::vector::data() ) to the second call to EnumMonitors() to fill the output buffer of the MONITOR_INFO_1 structure.

(Note: std::vector will automatically free its allocated memory when the function exits, both on the success path and on the path to throw exceptions.)

 #include <exception> // for std::exception #include <iostream> // for std::wcout, std::wcerr, std::endl #include <sstream> // for std::ostringstream #include <stdexcept> // for std::runtime_error #include <vector> // for std::vector #include <windows.h> // Win32 SDK main header #include <winspool.h> // for EnumMonitors() using namespace std; void ThrowOnApiFailure(const char* apiName, DWORD errorCode) { ostringstream errorMessage; errorMessage << apiName << "() failed with error code " << errorCode; throw runtime_error(errorMessage.str()); } void PrintMonitors() { static const int kMonitorInfoLevel = 1; // for MONITOR_INFO_1 // Ask output buffer size DWORD bufferSize = 0; DWORD infoCount = 0; ::EnumMonitors( nullptr, kMonitorInfoLevel, nullptr, 0, // ask buffer size &bufferSize, &infoCount); DWORD error = ::GetLastError(); if (error != ERROR_INSUFFICIENT_BUFFER) { ThrowOnApiFailure("EnumMonitors", error); } // Size output buffer vector<BYTE> buffer(bufferSize); // Fill buffer with monitor info if ( ! ::EnumMonitors( nullptr, kMonitorInfoLevel, buffer.data(), buffer.size(), &bufferSize, &infoCount ) ) { error = ::GetLastError(); ThrowOnApiFailure("EnumMonitors", error); } // Print monitor info const MONITOR_INFO_1 * monitorInfo = reinterpret_cast<const MONITOR_INFO_1*>(buffer.data()); for (DWORD i = 0; i < infoCount; i++) { wcout << monitorInfo[i].pName << endl; } } int main() { try { PrintMonitors(); } catch(const exception& e) { wcerr << "\n*** ERROR: " << e.what() << endl; } } 
+1
source

You pass "0" for the second parameter. It must be 1 (or 2).

By MSDN

Level [in] Version of the structure pointed to by pMonitors.

This value can be 1 or 2.

0
source

All Articles