The MASM Forum

General => The Workshop => Topic started by: jj2007 on April 10, 2020, 12:26:55 PM

Title: A recent Windows 10 build punishes you for your sloppy coding
Post by: jj2007 on April 10, 2020, 12:26:55 PM
Special thanks to our new member TioPepperoni, who helped me hunting down a thoroughly hidden bug :thup:

This used to work fine in WinXP, Win7 and Win10:
sometest proc
Local buffer[8000]:BYTE
  lea edi, buffer
  invoke GetWindowTextW, hEdit, edi, 8000
  print edi
  ret
sometest endp


With this recent Windows 10 version, it fails silently - GetLastError reports no error but also no characters copied:
  OS: Windows 10 Pro (x64)
  Version: 1903
  Build: 18362.720

On my Italian OS, Version 1903 Build 18362.592, GetWindowTextW still works fine. My suspicion is that the new OS version checks if the buffer passed is really OK - and it's not, because the "W" wants chars, not bytes. So potentially, if the control has more than 8000 bytes of text, GetWindowTextW would trash the buffer including those precious bytes that allow sometest to return.

Usually, you can allocate slightly less than 3 pages, i.e. 3*4096 bytes as local variables without running into problems. That seems to have changed. You have been warned :badgrin:
Title: Re: A recent Windows 10 build punishes you for your sloppy coding
Post by: K_F on April 11, 2020, 12:20:49 AM
Thinking ?
No chance of your page-size being changed somewhere.
Title: Re: A recent Windows 10 build punishes you for your sloppy coding
Post by: Biterider on April 11, 2020, 12:50:28 AM
Hi JJ
On my OS I can not reproduce this bug. GetWindowTextW returns the caption as expected (with a short wide string).
No doubt that the 8000 is wrong.

Biterider
Title: Re: A recent Windows 10 build punishes you for your sloppy coding
Post by: jj2007 on April 11, 2020, 12:00:25 PM
Hi Biterider,

Strange, because your build number is higher. I suppose Tio's OS is the US English version, mine is Italian, yours is German. What's going on? My suspicion was that the OS either runs into a guard page (but how?), or that it checks explicitly for a buffer overwrite by comparing the start pos against esp/ebp. Unfortunately I can't debug it myself :sad:
Title: Re: A recent Windows 10 build punishes you for your sloppy coding
Post by: Biterider on April 11, 2020, 03:41:34 PM
Hi JJ
Can you provide the test executable that is causing the issue compiled with debug information and the pdb file?
I'll try here to check if the operating system is causing the problem.  :icon_idea:

Biterider
Title: Re: A recent Windows 10 build punishes you for your sloppy coding
Post by: jj2007 on April 11, 2020, 10:16:39 PM
Quote from: Biterider on April 11, 2020, 03:41:34 PM
Can you provide the test executable that is causing the issue compiled with debug information and the pdb file?
I'll try here to check if the operating system is causing the problem.  :icon_idea:

Attached, but no pdb file. I see the symbols, though, in Olly. Note you need a current MasmBasic (http://masm32.com/board/index.php?topic=94.0) installation to use it. The effect is subtle: When hitting F6, it builds whatever source fine, the exe is there, but on Tio's machine it doesn't launch the exe because GetWindowTextW does not fill the buffer. GetLastError returns zero, GetWindowTextW returns zero chars copied.

The invoke GetWindowTextW is at 40877E

Extract the exe as \Masm32\MasmBasic\ReTestDebug.exe and just launch it. Then go File/New Masm source, pick e.g. a standard Masm32 SDK example from the top and hit F6.
Title: Re: A recent Windows 10 build punishes you for your sloppy coding
Post by: Biterider on April 12, 2020, 01:13:38 AM
Hi JJ
I deleted the complete MASMBASIC folder and reinstalled it using the link you provided.
The installation ended with an error. A dialog was displayed stating that the module msptls.dll is missing.
I closed the dialog and double-clicked the exe from the attachment.
A new dialog with the message that "Res\RichMasmGuide.asc cannot be opened" was displayed.
I closed the dialog and a huge cyan blank window appeared. I pressed F6 and a new dialog with the message "...\Desktop\Res\ bldallRM.bav was not found" was displayed.

Maybe a plain MASM exe will be a better way to test described behavior.  :icon_idea:

Biterider


Title: Re: A recent Windows 10 build punishes you for your sloppy coding
Post by: jj2007 on April 12, 2020, 01:34:11 AM
Thanks for the feedback. You might have an incomplete RichEdit installation. Please check if you can find
C:\Program Files (x86)\Common Files\microsoft shared\OFFICE1?\MSPTLS.DLL
If the editor, i.e. \Masm32\MasmBasic\RichMasm.exe, starts at all, press F9 to see the RichEdit version used (in the last two lines). RichMasm checks if the user has any MS Office stuff available, and picks the best RichEd20.dll version, which is Office12 in my case. Office11 is ok, Office14 and higher are somewhat buggy...

> I pressed F6 and a new dialog with the message "...\Desktop\Res\ bldallRM.bav was not found" was displayed
The exe in the archive ReTestDebug.zip cannot run from an arbitrary folder. It must be extracted as \Masm32\MasmBasic\ReTestDebg.exe, otherwise it won't find a dozen little helpers.
Title: Re: A recent Windows 10 build punishes you for your sloppy coding
Post by: Biterider on April 12, 2020, 07:35:31 AM
Hi JJ
I managed to run the application. With Olly I reproduced the behavior you described. GetWindowTextW returned eax = 0.
If I change the argument (buffer size) to 4000, GetWindowTextW returns eax = 0F1h and fills the buffer with this wide string:
Quote** Start D:\MASM32\MasmBasic\Res\bldallRM.bat **
**** 32-bit assembly ****

*** Assemble, link and run RichMasmGuide ***

*** Assemble using UAsm64  ***
Error A2106: Cannot open file: "tmp_file.asm" [ENOENT]
*** Assembly Error ***

The I changed the debugger to VS. Now the API behaves correctly and returns the same string. What I noticed is that the guard page is a few hundert bytes away.
The API may fail because the guard page throws an exception. Try probing the stack before calling GetWindowTextW.

Biterider

Title: Re: A recent Windows 10 build punishes you for your sloppy coding
Post by: jj2007 on April 12, 2020, 03:45:10 PM
Quote from: Biterider on April 12, 2020, 07:35:31 AMThe API may fail because the guard page throws an exception.

Thanks for confirming this. Of course, putting 8000 there was a bug.

The interesting aspect here is that apparently they made a tiny little change in the architecture. Despite this bug, it worked fine on WinXP, Win7, and my version of Win10. Now it fails due to the guard pages being set differently.

We might see other software fail, since sloppy coding is not restricted to myself. Adobe, for example, greets me with a "corrected" new version after each and every boot :badgrin:
Title: Re: A recent Windows 10 build punishes you for your sloppy coding
Post by: morgot on April 15, 2020, 08:34:07 AM
Local buffer[8000]:BYTE - is very huge for stack

In my Win10x64 it dont fail.. Or I dont see it.


sometest proc
Local buffer[8000]:BYTE
  call GetShellWindow
  mov ebx,eax
 
  lea edi, buffer
 
  invoke GetWindowTextW, ebx, edi, 8000
  print edi
  ret
sometest endp
end start


type "Program manger"
Title: Re: A recent Windows 10 build punishes you for your sloppy coding
Post by: hutch-- on April 22, 2020, 10:35:04 AM
morgot,

You need to preserve the non volatile registers.

sometest proc
Local buffer[8000]:BYTE

  push ebx
  push edi

  call GetShellWindow
  mov ebx,eax

  lea edi, buffer

  invoke GetWindowTextW, ebx, edi, 8000
  print edi

  pop edi
  pop ebx

  ret
sometest endp
end start
Title: Re: A recent Windows 10 build punishes you for your sloppy coding
Post by: TimoVJL on April 22, 2020, 03:46:12 PM
Quote from: hutch-- on April 22, 2020, 10:35:04 AM

sometest proc
Local buffer[8000]:BYTE
...

  invoke GetWindowTextW, ebx, edi, 8000

buffer size 8000 bytes, no stack check, GetWindowTextW nMaxCount is characters ?
Title: Re: A recent Windows 10 build punishes you for your sloppy coding
Post by: hutch-- on April 22, 2020, 04:32:57 PM
See what I suggested.

You need to preserve the non volatile registers.
......
  push ebx
  push edi
......

  pop edi
  pop ebx

The rest is unmodified.
Title: Re: A recent Windows 10 build punishes you for your sloppy coding
Post by: jj2007 on April 22, 2020, 05:52:03 PM
Quote from: TimoVJL on April 22, 2020, 03:46:12 PMbuffer size 8000 bytes, no stack check, GetWindowTextW nMaxCount is characters ?

Exactly. So in the unlikely case that the window has a text that is 4010 characters long, your ret address would be overwritten, and you end up in no man's land on any Windows version. That's why the title has "sloppy coding" in it.

What's new is that in certain*) recent Win10 versions the attempt of GetWindowTextW to write to [esp-8000] fails silently, as explained above.

The mystery here is that it works just fine if you reduce nMaxCount to 4000 chars. I call it a "mystery" because GetWindowTextW still writes to the same address, obviously. So the lack of stack probing is not the explanation. The only rational explanation I have is that GetWindowTextW checks if writing to the end of the buffer would pass by esp:
mov edi, pBuffer
mov ecx, nMaxCount
lea edx, [edi+ecx]
.if edx>esp && edi<esp
  ; invoke SetLastError, YouTrashYourStackIdiot
  xor eax, eax
  ret
.endif


That is technically possible but a) it's too clever a trick for Microsoft coders and b) the SetLastError bit is missing :cool:

Unfortunately I can't test it with a debugger because my (Italian) Win10 still works as before.

*) You have the new version if hitting F6 in the current RichMasm version (here (http://masm32.com/board/index.php?topic=94.0)) assembles a hello world but does not run it.
Title: Re: A recent Windows 10 build punishes you for your sloppy coding
Post by: hutch-- on April 23, 2020, 12:37:20 PM
If unknown text length is the problem, scan the source and get either its length or character count then dynamically allocate at least that much memory. Either HeapAlloc() or GlobalAlloc() will do the job, I don't see what the big deal is about.
Title: Re: A recent Windows 10 build punishes you for your sloppy coding
Post by: jj2007 on April 23, 2020, 08:06:43 PM
No, unknown text length is not the problem.
Title: Re: A recent Windows 10 build punishes you for your sloppy coding
Post by: jj2007 on May 03, 2020, 10:16:22 PM
Unrelated, but I didn't want to open a new thread: have you ever compared the built-in original Micros**t image viewer to a Gdi+ viewer? This is Win7-64, I hope they've improved on Win10 :cool:
Title: Re: A recent Windows 10 build punishes you for your sloppy coding
Post by: JoeBr on May 06, 2020, 03:31:43 AM
Can't open the zip - after updating 7-Zip to the most recent version.  What app did you use to create it?

Joe
Title: Re: A recent Windows 10 build punishes you for your sloppy coding
Post by: jj2007 on May 06, 2020, 05:40:21 AM
Joe, that's just a png renamed to zip. If you want to test the viewer, unzip the attached exe to a folder containing images.
The menus don't do anything. To zoom the image, click once into the caption, then use the mousewheel.

It's work in progress, the source is far too confused to be shown :tongue:
Title: Re: A recent Windows 10 build punishes you for your sloppy coding
Post by: JoeBr on May 06, 2020, 05:55:21 AM
Ah - Ok - Thanks.

Joe
Title: Windows 10 is unusable, and WM_MOUSEWHEEL is broken
Post by: jj2007 on May 21, 2020, 09:36:57 AM
I wanted to test some stuff on Win 10, so I launched my wife's notebook, which is about 4 years old (I stick to Windows 7).
Micros**t... what are your intentions? I had wondered why my wife prefers her smartphone, now I understand: Win10 is utterly slow. Unusable. Updating all the time, but even when there is a slot without updating, it is just annoyingly slow, as if you tried to swim in a pool of honey. Do I have to switch off the bloody AV?[/rant]

One interesting observation: WM_MOUSEWHEEL works differently!

Attached is my current image viewer (work in progress but it works just fine):
On Win7-64, point the mouse into an image and turn the wheel. Zoom!
On Win10, no zoom at all. It took me quite a while to find out what's happening: on Win10, the message arrives only if the mouse is outside the child window, e.g. in the window caption.

Shall we call that a bug, or is it a new feature, Redmond?

Apparently few people noticed this; here is one (https://stackoverflow.com/questions/11034348/mouse-wheel-event-to-work-with-hovered-control):
QuoteIt seems they made "scroll whatever the mouse cursor is over" the standard behaviour in Windows 10. Which is kind of annoying in most cases, actually. – Nyerguds Aug 12 '15 at 17:49

Another one: Broken WM_MOUSEWHEEL's mouse cursor position in Windows 10 (https://conemu.github.io/en/MicrosoftBugs.html#WM_MOUSEWHEEL-10)

The Chromium developers had this problem too: Seems we aren't getting WM_MOUSEWHEEL events but are getting events with message 0x0250 in its place. (https://bugs.chromium.org/p/chromium/issues/detail?id=647038)
Title: Re: A recent Windows 10 build punishes you for your sloppy coding
Post by: hutch-- on May 21, 2020, 10:25:18 AM
I know of a guy who lives in the country well away from fast internet access who had a very ordinary laptop with Win10 on it and the endless updates exceed his bandwidth allowance and has rendered his laptop useless. On big machines with high speed internet access in city areas, Win10 64 bit works fine (If you spend long enough setting it up) but for limited bandwidth on an older laptop, its a disaster.

Have a look at Linux Mint 19.3 Tricia, much smaller footprint, no auto updates and if you are not writing Windows software, you can get some massive amount of software that can do a massive number of things for gratis.

I did a test run on an Intel board over 10 years old with 4 gig of memory and a 2.4 gig Core2 Quad and it ran really well.
Title: Re: A recent Windows 10 build punishes you for your sloppy coding
Post by: Vortex on May 21, 2020, 07:29:44 PM
Hi Jochen,

Could you get a solid state disk and transfer the operating system to this one? Solid disk improves a lot the performance.