4

We have several old C++ Windows applications that have stopped working after the Windows Creators Update. Like many C++ devs, we had created C++ wrappers that encapsulated the Windows API. We stored and retrieved our this pointers via Set/GetWindowsLongPtr(), like this (see here for more info on how one does this):

Window=(cWindow*) GetWindowLongPtr(hWnd,GWLP_USERDATA);

That worked well for 20 or so years, but with this latest Windows update I am seeing rogue messages in our message loop that aren't from our windows. GetWindowsLongPtr() returns a pointer that is not one of ours, which causes all sorts of memory access issues. So far, I've seen that the class name of these rogue windows is "UserAdapterWindowClass", so I can filter message handling based on this (my cheesy work-around).

What is this new Windows class? What is it's purpose? Are there any others?

Marc Bernier
  • 2,928
  • 27
  • 45
  • 1
    I have been preaching, literally for **decades**: Don't store your instance pointers in `GWLP_USERDATA`. It's virtually public domain. Everyone has access to it, and everyone (and their dogs) do use that convenient place to store per-window data. If you register the window class, set aside space in the `cbWndExtra` memory. If you don't, use window properties with unique names (calling `SetProp` with the string representation of a GUID). It was about time this started to fail. – IInspectable Jun 06 '17 at 16:47
  • 1
    Generic message loop may process messages from any windows and applications may contain windows that you didn't create, there is nothing new about this. Storing raw pointer and just casting it like this is way too optimistic, the better approach would be to store a cookie and perform lookup for corresponding window object. – user7860670 Jun 06 '17 at 16:49
  • 1
    @VTT: Not an issue. `DispatchMessage` knows which window procedure to call. – IInspectable Jun 06 '17 at 16:53
  • 2
    " So far, I've seen that the class name of these rogue windows is "UserAdapterWindowClass", ..." -- fire up Spy++ 64, search, get process ID, get process EXE. What is it? – Dave S Jun 06 '17 at 17:00
  • @Dave S - that's the thing, they don't appear in Spy++! – Marc Bernier Jun 06 '17 at 17:18
  • @IInspectable: Agreed, but this was done before we had the luxury of looking stuff up on the Internet. I seem to recall that I figured out this 'trick' by poring over MFC and OWL source code. – Marc Bernier Jun 06 '17 at 17:24
  • `I am seeing rogue messages in our message loop that aren't from our windows.` - and so what ? system internal can create additional windows. `GetWindowsLongPtr() returns a pointer that is not one of ours` - but are you **set** your context via `GWLP_USERDATA` to this window ? you subclass this window and then your context was changed or in what problem ? – RbMm Jun 06 '17 at 17:43
  • I doubt, though, that this is something to do with the Windows Update. More likely than not, this is some application (a self-acclaimed *"productivity"* or *"power"* tool), that didn't transition over as smoothly as one would have hoped, and now uses a fallback implementation that thrashes foreign territory. – IInspectable Jun 07 '17 at 07:51
  • 1
    That `UserAdapterWindowClass` window and the associated 0x738 (WM_USER+824) messages which literally FLOOD my message queue are currently driving me mad. Did you happen to have more information? – manuell Apr 26 '18 at 10:04

1 Answers1

0

You shouldn't be be using GetWindowLongPtr(hWnd, GWLP_USERDATA) outside of your own window procedure function. It is well-documented that windows you did not create yourself will be part of the message queue, but they will be dispatched to the appropriate place on their own and you need only worry about messages that get dispatched to your window prodecure. This is especially true for Windows controls like edit boxes and such.

Experiencing a crash such as yours is a sign of improper design on your part, but you can mitigate it by using GetClassWord(hwnd, GCW_ATOM) and checking it against the ATOM you got from RegisterClass or RegisterClassEx, or alternatively, you can check the window class name if you don't mind the even worse performance hit. I recommend refactoring your program to not use GWLP_USERDATA outside of the window procedure though.

LB--
  • 2,506
  • 1
  • 38
  • 76