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:
Thinking ?
No chance of your page-size being changed somewhere.
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
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:
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
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.
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
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.
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
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:
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"
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
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 ?
See what I suggested.
You need to preserve the non volatile registers.
......
push ebx
push edi
......
pop edi
pop ebx
The rest is unmodified.
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.
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.
No, unknown text length is not the problem.
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:
Can't open the zip - after updating 7-Zip to the most recent version. What app did you use to create it?
Joe
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:
Ah - Ok - Thanks.
Joe
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)
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.
Hi Jochen,
Could you get a solid state disk and transfer the operating system to this one? Solid disk improves a lot the performance.