Malformed call to ChangeDisplaySettings() causing BSOD on Windows 7 - windows

The following program causes a BSOD on my fully patched Windows 7 machine and a Windows 7 machine of a colleague - the systems are very different configurations so I don't think it's a driver issue. It seems that something just can't handle a request for a display mode that only includes a zero display frequency. Here's the code that triggers a BSOD under Visual Studio 2012 Update 3:
#include <windows.h>
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
DEVMODE mode = { 0 };
mode.dmSize = sizeof(DEVMODE);
mode.dmFields = DM_DISPLAYFREQUENCY;
ChangeDisplaySettings(&mode, CDS_FULLSCREEN);
return 0;
}
Adding the following line prior to ChangeDisplaySettings() stops the BSOD occurring:
mode.dmDisplayFrequency = 60;
The BSOD details are:
*** STOP 0x0000007E (0xFFFFFFFFC0000094, 0xFFFFF96000685577, 0xFFFFF88015313638, 0xFFFFF88015312E90)
*** cdd.dll - Address FFFFF96000685577 base at FFFFF96000680000, DateStamp 4d4a90a5
I'm posting this as a question because I'm interested if anyone else has noticed it or has any comments, and also so that a cause of this particular BSOD is out there in case it helps anyone in the future.
Also interested in whether others are able to reproduce it reliably as well.
If you post a thoughtful/interesting/relevant response/answer/discussion then the rep is yours!

Related

How to check the result of PrintUIEntry call

I'd like to use PrintUIEntryW (of printui.dll ) to install a printer driver on Windows system. My code looks like following (pseudo).
m = LoadLibrary(L"printui.dll");
printuientry = GetProcAddress(m, "PrintUIEntryW");
// set arg_string
printuientry(NULL, m, arg_string, SW_SHOW);
Could I check the return value of the function or something like GetLastError() to check if the desired call is successful? There seems no msdn entry for this function.
Thanks in advance.
PrintUIEntry is documented here:
Rundll32 printui.dll,PrintUIEntry
rundll32 is documented is here:
INFO: Windows Rundll and Rundll32 Interface
Most importantly:
In your DLL, write the function with the following prototype:
16-bit DLL:
void FAR PASCAL __loads EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
32-bit DLL:
void CALLBACK EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
...
On Windows NT, Windows 2000, and Windows XP the behavior of Rundll32.exe is slightly different, in order to accommodate UNICODE command lines.
Windows NT first attempts to GetProcAddress for W. If this entry point is found, then the prototype is assumed to be:
void CALLBACK EntryPointW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow);
This is the same as the ANSI EntryPoint, except that the lpszCmdLine parameter is now a UNICODE string.
As you can see, functions designed to be used with rundll32 do not have a return value. And PrintUIEntry is not documented as using SetLastError() for error reporting. So, in this case, you cannot do any kind of error handling. You will have to use a different API that reports errors.

Error LNK2019 in visual studio in win32 application?

I have making an attempt at writing my first program in Visual Studio, however am being troubled by an error.
It says: -
Error 3 error LNK2019: unresolved external symbol _wWinMain#16 referenced in function ___tmainCRTStartup
E:\Documents\Programming\Software Development\Microsoft Development\Microsoft Development\MSVCRTD.lib(wcrtexew.obj)
Microsoft Development
On researching I found similar errors, but none have helped me solve the problem.
I have changed the entry point to
wWinMainCRTStartup
the character set to Unicode
the subsystem to console. The project is a win32 application. The code is as follows: -
#include <windows.h>
#include <stdio.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MessageBox(NULL, "Hello World!", "Note", 1/*MB_OK*/);
printf("nCmdShow = %d\n", nCmdShow);
return 0;
}
How do I fix this issue?
P.S. I am using Visual Studio Ultimate 2013
For a Unicode build your code needs to be more like this:
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPWSTR lpCmdLine, int nCmdShow)
{
MessageBox(NULL, L"Hello World!", L"Note", 1/*MB_OK*/);
printf(L"nCmdShow = %d\n", nCmdShow);
return 0;
}
At least by default this will be set to use the Windows subsystem (because the entry point is named a variant of WinMain). You can force that to the console subsystem (-subsystem:console flag to the linker) or get it to happen by default by changing the entry point to a variant of main instead:
int wmain(int argc, wchar_t **argv) { // ...
Obviously you won't be able to print nCmdShow using this though (not that it really means anything in a console program). For that matter, since you're not using the command line arguments anyway, you can simplify this somewhat to:
int wmain(){ // ....
Actually, nCmdShow is basically obsolete even for windowed programs. The first time a windowed program calls ShowWindow, it normally passes nCmdShow as the parameter. Windows, in turn, ignores the value passed in the first call to ShowWindow, and instead uses the value from the process' STARTUPINFO structure. Only in subsequent calls to ShowWindow is the parameter used (and for these subsequent calls, you're not supposed to pass nCmdShow either--you're supposed to pass one of the defined constants such as SW_SHOWNORMAL).
Reference: MSDN entry for ShowWindow
A Win32 application starts at WinMain. A console application starts at main. Your question implies you have a confused mixture of the two.
Just use the File, New, Project menu command to let Visual Studio build a skeleton of the type of application you have in mind.

How to COMPLETELY hide console in a Win32 program?

With the code below, the console is hidden BUT it appears for about 1 second.
How can I completely hide the console ?
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <iostream>
using namespace std;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdLine, int cmdShow){
HWND hWnd = GetConsoleWindow();
ShowWindow( hWnd, SW_HIDE );
MessageBox(NULL, TEXT("Hello!"), TEXT("yuhuuu"), 0);
return 0;
}
Something is weird with your compiler settings. (You did not specify your compiler so I'm assuming MSVC)
The WinMain entry point function from your example is used by GUI applications (Linker switch /SUBSYSTEM:WINDOWS) and those applications don't get a console unless you call AllocConsole.
If you link with /SUBSYSTEM:CONSOLE then Windows will create a console for the process before your code is executed but a normal entry point for those applications is the plain old main function.
Are you forcing the entry point with the /ENTRY switch? Either way, make sure the /SUBSYSTEM switch and the entry point function definition are compatible and match the type of application you want to create (GUI or console)

Why does calling ProcessGroupPolicyEx callback cause an access violation?

I'm trying to help a colleague with some code in a client side extension. Since adding in a call to the callback, the function seems to complete ok, but an event in the Windows Event log complains about an access violation whilst processing the group policy object.
After removing existing code, with just the added call to the callback, it still reports this access violation.
Can you please help identify what we might be missing?
//
// Entry point for processing group policy objects.
//
// For full details, see http://msdn.microsoft.com/en- us/library/windows/desktop/aa374383(v=vs.85).aspx.
//
extern "C" DWORD CALLBACK ProcessGroupPolicyEx (
__in DWORD dwFlags,
__in HANDLE hToken,
__in HKEY hKeyRoot,
__in PGROUP_POLICY_OBJECT pDeletedGPOList,
__in PGROUP_POLICY_OBJECT pChangedGPOList,
__in ASYNCCOMPLETIONHANDLE pHandle,
__in BOOL *pbAbort,
__in PFNSTATUSMESSAGECALLBACK pStatusCallback,
__in IWbemServices *pWbemServices,
__out HRESULT *pRsopStatus)
{
if(pStatusCallback)
pStatusCallback (FALSE, L"Aaaaargh!");
return (0);
}
This code has been tried using a static string, an array of bytes on the stack, a array of bytes that's been new'd and deliberately leaked - in case the method was taking ownership of the memory. Also been CoTaskMemAlloc'd, just in case. All produce the same problem.
The (redacted) error in the eventlog is:
Windows cannot process Group Policy Client Side Extension Exception 0xc0000005.
To make things interesting, this is just on some OS's, fully patched XP 32bit is one of the definite problems. 2008R2 works fine.
Yes - we need it to work on XP 32bit.
Other weird behaviour that may have a bearing here:
If we call this function multiple times, it fails on the 3rd call. No exception is thrown, no text is shown, none of our code after the call is executed, no additional errors in the event log. Timing is not a factor here: it happens if you call it 3 times in a row, or 3 times over 5 minutes.
This does not happen if we wrap the calls in a generic try/catch block. No exception is caught - all the text is shown. All the code is run.
We still get the error in the event log, however.
Looks like we've found the issue with this.
The problem is that the callback needs to be made with __stdcall calling convention.
By default, visual studio creates projects with the __cdecl calling convention.
If you add the /Gz flag to your project, it will use __stdcall by default. We couldn't do that, however, since we're pulling in other modules with different calling conventions.
The underlying problem is that UserEnv.h defines the callback like this:
typedef DWORD (*PFNSTATUSMESSAGECALLBACK)(__in BOOL bVerbose, __in LPWSTR lpMessage);
This is a strange definition. All other windows callbacks are defined like this:
typedef INT_PTR (CALLBACK* DLGPROC)(HWND, UINT, WPARAM, LPARAM);
That CALLBACK is important, it expands like this:
#define CALLBACK __stdcall
This means that by default, all windows callbacks are defined to use __stdcall calling conventions, except this one, for some reason.
If we create our own callback defintion:
typedef DWORD (CALLBACK *PFNSTATUSMESSAGECALLBACK_STDCALL)(__in BOOL bVerbose, __in LPWSTR lpMessage);
And assign our function pointer to it:
PFNSTATUSMESSAGECALLBACK_STDCALL pStatusCallback = (PFNSTATUSMESSAGECALLBACK_STDCALL)pRawStatusCallback;
Then we can use the pStatusCallback function pointer with the __stdcall calling convention and have things work properly.

GetIpAddrTable() leaks memory. How to resolve that?

On my Windows 7 box, this simple program causes the memory use of the application to creep up continuously, with no upper bound. I've stripped out everything non-essential, and it seems clear that the culprit is the Microsoft Iphlpapi function "GetIpAddrTable()". On each call, it leaks some memory. In a loop (e.g. checking for changes to the network interface list), it is unsustainable. There seems to be no async notification API which could do this job, so now I'm faced with possibly having to isolate this logic into a separate process and recycle the process periodically -- an ugly solution.
Any ideas?
// IphlpLeak.cpp - demonstrates that GetIpAddrTable leaks memory internally: run this and watch
// the memory use of the app climb up continuously with no upper bound.
#include <stdio.h>
#include <windows.h>
#include <assert.h>
#include <Iphlpapi.h>
#pragma comment(lib,"Iphlpapi.lib")
void testLeak() {
static unsigned char buf[16384];
DWORD dwSize(sizeof(buf));
if (GetIpAddrTable((PMIB_IPADDRTABLE)buf, &dwSize, false) == ERROR_INSUFFICIENT_BUFFER)
{
assert(0); // we never hit this branch.
return;
}
}
int main(int argc, char* argv[]) {
for ( int i = 0; true; i++ ) {
testLeak();
printf("i=%d\n",i);
Sleep(1000);
}
return 0;
}
#Stabledog:
I've ran your example, unmodified, for 24 hours but did not observe that the program's Commit Size increased indefinitely. It always stayed below 1024 kilobyte. This was on Windows 7 (32-bit, and without Service Pack 1).
Just for the sake of completeness, what happens to memory usage if you comment out the entire if block and the sleep? If there's no leak there, then I would suggest you're correct as to what's causing it.
Worst case, report it to MS and see if they can fix it - you have a nice simple test case to work from which is more than what I see in most bug reports.
Another thing you may want to try is to check the error code against NO_ERROR rather than a specific error condition. If you get back a different error than ERROR_INSUFFICIENT_BUFFER, there may be a leak for that:
DWORD dwRetVal = GetIpAddrTable((PMIB_IPADDRTABLE)buf, &dwSize, false);
if (dwRetVal != NO_ERROR) {
printf ("ERROR: %d\n", dwRetVal);
}
I've been all over this issue now: it appears that there is no acknowledgment from Microsoft on the matter, but even a trivial application grows without bounds on Windows 7 (not XP, though) when calling any of the APIs which retrieve the local IP addresses.
So the way I solved it -- for now -- was to launch a separate instance of my app with a special command-line switch that tells it "retrieve the IP addresses and print them to stdout". I scrape stdout in the parent app, the child exits and the leak problem is resolved.
But it wins "dang ugly solution to an annoying problem", at best.

Resources