News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Windows plays foul with tooltips_class32

Started by jj2007, January 21, 2011, 01:59:14 PM

Previous topic - Next topic

jj2007

Alex,
You are splitting hairs. CwEx should set LastError to zero, even if internal calls fail. Worse is the behaviour of LoadString

.data?
bufferx db 1000 dup(?) ; Stringtable ID 01 is "Enter text here"
.code
invoke LoadString, hInstance, 999, offset bufferx, 5 ; size too small
mov esi, offset bufferx
mov edi, eax
mov eax, LastError$()
deb 4, "LoadString bugs:", edi, $eax, $esi


invoke LoadString, hInstance, 01, offset bufferx, -3 ; negative size
LoadString bugs:
edi             -4  (=-4 characters successful copied, congrats...)
$eax            Operazione completata = OK
$esi            (empty string)

invoke LoadString, hInstance, 01, offset bufferx, 5 ; size too small
LoadString bugs:
edi             4
$eax            Operazione completata.
$esi            Ente

invoke LoadString, 0, 01, offset bufferx, 5 ; zero hInstance, size too small
LoadString bugs:
edi             4
$eax            Operazione completata.
$esi            Ente

invoke LoadString, 0, -99, offset bufferx, 5 ; zero hInstance, size too small, wrong ID
LoadString bugs:
edi             0
$eax            Can't find the name of the resource
$esi

Antariy

Quote from: jj2007 on January 22, 2011, 01:55:48 AM
Alex,
You are splitting hairs. CwEx should set LastError to zero, even if internal calls fail.

I'll not say anything more, since I'm splitting hairs (as usual).

CWEx *should NOT SetLastError if it succeeded*. No ANY APY should set it if succeeded. This is documented behavious which you may rely. "Some" apis set last error to 0, but not all and number of that apis is very small. If API set SLE it even if succeeded, then this is just favour, not rule.

MichaelW

In my test of this under Windows 2000 CreateWindowEx returned a handle and GetLastError returned ERROR_SUCCESS.

Per the PSDK documentation for GetLastError:

"The GetLastError function retrieves the calling thread's last-error code value.
. . .
You should call the GetLastError function immediately when a function's return value indicates that such a call will return useful data. That is because some functions call SetLastError with a zero when they succeed, wiping out the error code set by the most recently failed function."

Within my experience most functions do not reset the last error value on success.

eschew obfuscation

jj2007

Quote from: Antariy on January 22, 2011, 02:06:25 AMCWEx *should NOT SetLastError if it succeeded*. No ANY APY should set it if succeeded. This is documented behavious which you may rely. "Some" apis set last error to 0, but not all and number of that apis is very small. If API set SLE it even if succeeded, then this is just favour, not rule.

As a matter of fact, CwEx changes lasterror to an obscure message in spite of the fact that it succeeds, and a subsequent API, LoadString, does not change lasterror in spite of the fact that it fails. It is by sheer accident that I was able to track down the reason for this behaviour.

MichaelW

Quote from: jj2007 on January 22, 2011, 02:12:01 AM
As a matter of fact, CwEx changes lasterror to ...

Are you sure that CwEx changed it? CwEx probably calls many other functions, and its success may depend on one or more of these called functions returning an error.



eschew obfuscation

jj2007

Quote from: MichaelW on January 22, 2011, 02:22:56 AM
Quote from: jj2007 on January 22, 2011, 02:12:01 AM
As a matter of fact, CwEx changes lasterror to ...
Are you sure that CwEx changed it? CwEx probably calls many other functions, and its success may depend on one or more of these called functions returning an error.

Michael,
That is a strange argument. If one of your procedures uses a WinAPI, and finds out, for example, that a file is missing, does it report "all is fine", or does it pass on the message...?

japheth

Quote from: jj2007 on January 22, 2011, 02:12:01 AM
As a matter of fact, CwEx changes lasterror to an obscure message in spite of the fact that it succeeds, and a subsequent API, LoadString, does not change lasterror in spite of the fact that it fails. It is by sheer accident that I was able to track down the reason for this behaviour.

This is partly a misconception. CreateWindowEx may change last error to any value it likes as long as it succeeds, since the value of "last error" is to be regarded as undefined if the function doesn't fail.

LoadString() returning 0 and not setting "last error" would be a true bug. However, when I  try this, the OS (WinXP SP2) always returns error code 1812 (ERROR_RESOURCE_DATA_NOT_FOUND), which sounds plausible.

MichaelW

Quote from: jj2007 on January 22, 2011, 02:44:31 AM
That is a strange argument. If one of your procedures uses a WinAPI, and finds out, for example, that a file is missing, does it report "all is fine", or does it pass on the message...?

What about a procedure that needs to use a file of a given name if it exists, or create the file if it does not exist? How do you go about determining if the file exists?

eschew obfuscation

sinsi

Have you tried calling SetLastError with an unusual value before the API call?
Most functions won't change it if they succeed.

Maybe you could put a watch in a debugger on the error code variable? It should be in the TIB somewhere.
Light travels faster than sound, that's why some people seem bright until you hear them.

jj2007

Quote from: MichaelW on January 22, 2011, 08:21:31 AM
What about a procedure that needs to use a file of a given name if it exists, or create the file if it does not exist? How do you go about determining if the file exists?

I would return 1 for "file existed" and 2 for "file was created", but definitely not "I used the file you indicated, but I won't tell you if it existed or not, and by the way, you should be ashamed because you impersonated the wrong token" :wink

@Sinsi: That's what I did: invoke SetLastError, 1. The value persists with LoadString (and LoadStringW), in spite of eax==0 returned.

jj2007

Quote from: japheth on January 22, 2011, 05:05:42 AM
LoadString() returning 0 and not setting "last error" would be a true bug. However, when I  try this, the OS (WinXP SP2) always returns error code 1812 (ERROR_RESOURCE_DATA_NOT_FOUND), which sounds plausible.

Here is the relevant part of the code - attached the executable and the *.asc file (MasmBasic and RichMasm needed to assemble the source).

         MbToolExS = WS_EX_TOPMOST
         MbToolFlags = TTS_BALLOON
         invoke SetLastError, 1
         invoke CreateWindowEx, MbToolExS, chr$("tooltips_class32"), ebx,
         MbToolFlags, ebx, ebx, ebx, ebx, hWnd, ebx, hInstance, ebx
         mov [esi-4], eax      ; store handle in hMbTIS
         xchg eax, edi
;         mov eax, LastError$()
;         deb 1, "Create TT", edi, $eax
      .data?
         bufferx   db 1024 dup(?)      ; Stringtable ID 01 is "Enter text here"
      .code
         pushad
         invoke LoadString, hInstance, 3, offset bufferx, 1000
         mov esi, offset bufferx
         mov edi, eax
         mov eax, LastError$()
         deb 4, "LoadString bugs:", edi, $eax, $esi
         LoadString bugs:
         edi      0   ; retval
         $eax   Un thread che attualmente non rappresenta un client ha tentato di operare su un token di rappresentazione di client.
         popad

japheth

Quote from: jj2007 on January 22, 2011, 08:07:32 PM
Quote from: japheth on January 22, 2011, 05:05:42 AM
LoadString() returning 0 and not setting "last error" would be a true bug. However, when I  try this, the OS (WinXP SP2) always returns error code 1812 (ERROR_RESOURCE_DATA_NOT_FOUND), which sounds plausible.

Here is the relevant part of the code - attached the executable and the *.asc file (MasmBasic and RichMasm needed to assemble the source).

Thanks, but since I know that my code - which uses the pure Win32 API - works,  there are only a few possibilities left:

1.Japheth does something wrong
2. there's a big, fat bug in the Win XP LoadString function
3. JJ is doing something wrong
4. JJ's MasmBasic does something wrong
5. your machine is infected (rather unlikely)

IMO there is only one person left who can fix this issue ...

jj2007

Special edition for my clever German friend, with an int 3 before the LoadString - to be run with a debugger, obviously.

On my Win XP SP 2 machines, LoadString returns zero in eax (= an error) but keeps the error previously set by CreateWindowEx.

Grateful for feedback if others see the same error.

jj2007

Here another version. To make Japheth happy, I have called it LoadStringBugNoMB.zip  :bg

(which implies you can assemble it with the standard Masm32 package)

qWord

not sure ... but in your exe there is only one resource with the ID=3: an icon - maybe this is the problem. On Win7-x64 LoadString returns zero+ERROR_SUCCESS - so it has load an zero-sized string (icon data)?

qWord
FPU in a trice: SmplMath
It's that simple!