Search

GetCursorPos fails with large addresses in Large-Address-Aware 32-bit process (WPF) by EpicDarkVeil

Closed
as External Help for as External

17
0
Sign in
to vote
Type: Bug
ID: 381683
Opened: 11/13/2008 7:30:03 AM
Access Restriction: Public
1
Workaround(s)
7
User(s) can reproduce this bug
Calls to GetCursorPos always fail with ERROR_NOACCESS when passed an LPPOINT at a memory address higher than 2 GB. This is a common occurrence when running a 32-bit process that is Large Address Aware.

Windows Presentation Foundation uses GetCursorPos when handling window activation events and will throw a Win32Exception if GetCursorPos fails (returns 0.) This exception prevents WPF applications from receiving mouse focus! The WPF window will remain in an inactive state.

Attached is a repro case that demonstrates WPF becoming unresponsive due to GetCursorPos failing in a large-address-aware client.

The application allocates 2 GB of memory on the native heap and then loads a WPF DLL and displays a user interface. Every time the user clicks on the large button in the interface, thousands of items will be added to the list box. After a dozen clicks or so, when you resize the window WPF will pass a large address to GetCursorPos while handling an activation event. This call fails and WPF will throw an exception. The app will remain unreponsive to mouse input after that.
Details (expand)
Product Language
English

Version

Visual Studio 2008 SP1
Operating System
Windows Vista
Operating System Language
English
Steps to Reproduce
a) Make sure your computer has at least 4 GB of RAM installed. This is needed because we're testing large-address-aware behavior.
b) Unzip the attached Visual Studio 2008 project and load it up in the IDE
c) Rebuild the entire solution and run the "guinepig" C++/CLI appliction.
d) Follow the instructions in the displayed WPF window until the application becomes unresponsive.


----

Alternatively you can repro this by creating a test case that calls GetCursorPos with an address above 2 GB. The call will always fail.
Actual Results
a) GetCursorPos fails with large addresses.
b) WPF throws an exception and becomes unresponsive to mouse input.
Expected Results
a) GetCursorPos succeeds when passed an LPPOINT in an address below 3 GB in a large-address-aware 32-bit app.
b) WPF application remains responsive to mouse input.
TAP Code (if applicable)
 
      You can indicate your satisfaction with how Microsoft handled this issue by completing this quick 3 question survey. [Details]

 

File Attachments
File Name Submitted By Submitted On File Size  
small_guineapig.zip (restricted) 11/13/2008 -
Sign in to post a comment.
Posted by Esle on 4/28/2010 at 12:39 AM
This issue impacts not on the the RC of Visual Studio 2010, but the final version as well...
How the issue be escalated so that it can be fixed in Vista as well???
Posted by Ken Muse on 3/22/2010 at 3:23 PM
This issue also impacts the new Visual Studio 2010 RC (also a 32-bit app). This can make it very difficult to work with moderate to large projects on Vista x64. As the memory usage grows, eventually the ability to use the IDE can be lost. There are some workarounds, but it is ideal to be able to continue working on a project without risking the mouse functionality becoming disabled when your memory usage grows.
Posted by David Heffernan on 10/28/2009 at 5:22 PM
It's a bit disappointing that this fix won't be included in Vista. I suffer from the bug quite a bit. As it happens I'm building a native Delphi app and am able to replace calls to GetCursorPos with calls to GetCursorInfo which doesn't suffer from the large address bug.

Where I get bitten is by the HTML help viewer. Because that runs in an OCX (hhctrl.ocx) loaded into my process it inherits the large address aware setting and suffers a variety of problems which I presume are to do with this GetCursorPos bug. I suppose I could try and hook it but that seems a little dicey.

Incidentally and off-topic, the decision to implement the HTML help viewer in-process has some odd side-effects. The HTML help viewer component isn't theme aware and so when my help file is displayed by my app it does look a bit funny in places. When the help file is displayed outside my app (e.g. double-click the .chm) then the host (hh.exe) displays in classic mode. It would be nice if a future release of the HTML help viewer was theme-aware.
Posted by Microsoft on 2/17/2009 at 2:16 PM
EpicDarkVeil,

This bug is due to an issue in Windows. We have worked with the Win7 team to get this fixed in Win7, but unfortunately the Windows Serviceability Team (WinSE) rejected our request to downport this fix to Vista. You can try to escalate this issue to WinSE to get a downport.

Thanks!
Samantha
Program Manager, WPF Tree Services & Controls
Posted by Microsoft on 2/11/2009 at 2:54 AM
Thanks for your feedback. We are escalating this bug to the product unit who works on that specific feature area. The team will review this issue and make a decision on whether they will fix it or not for the next release.

Thank you,
Visual Studio Product Team
Sign in to post a workaround.
Posted by bionicbeagle on 2/5/2009 at 2:37 AM
Using EasyHook from CodePlex, I was able to quickly knock up a workaround:



#include <EasyHook.h>

TRACED_HOOK_HANDLE hGetCursorPos;

/*    Workaround for WPF bug with Large Address Aware

    Calls to GetCursorPos always fail with ERROR_NOACCESS when passed an
    LPPOINT at a memory address higher than 2 GB. This is a common occurrence
    when running a 32-bit process that is Large Address Aware.

    Windows Presentation Foundation uses GetCursorPos when handling window
    activation events and will throw a Win32Exception if GetCursorPos fails
    (returns 0.) This exception prevents WPF applications from receiving mouse
    focus! The WPF window will remain in an inactive state.
*/

BOOL WINAPI
hookedGetCursorPos(LPPOINT point)
{
    static POINT tempPoint;

    BOOL rv = GetCursorPos(&tempPoint);
    if (rv && point)
        memcpy(point, &tempPoint, sizeof tempPoint);

    return rv;
}

bool
installHooks()
{
    hGetCursorPos = new HOOK_TRACE_INFO;
    hGetCursorPos->Link = 0;

    HMODULE hUser32 = LoadLibraryA("user32.dll");
    NTSTATUS status = LhInstallHook(GetProcAddress(hUser32, "GetCursorPos"), hookedGetCursorPos, NULL, hGetCursorPos);

    ULONG threadList = 0;

    status = LhSetInclusiveACL(&threadList, 1, hGetCursorPos);

    return true;
}

Note that this quick hack does not clean up properly. I leave that as an exercise for the reader :P