The MASM Forum

General => The Workshop => Topic started by: jj2007 on May 27, 2022, 10:47:38 AM

Title: WM_ACTIVATEAPP problem
Post by: jj2007 on May 27, 2022, 10:47:38 AM
This message does not what I expect: it delivers IDs that look plausible but don't exist for Task Manager. What's going on? Full source attached, pure Masm32 SDK.

  CASE WM_ACTIVATEAPP
print str$(lParam), " is the thread ID", 13, 10
invoke LoadLibrary, chr$("Kernel32")
push eax
invoke GetProcAddress, eax, chr$("GetProcessIdOfThread")
.if eax
push lParam
call eax ; invoke GetProcessIdOfThread, lParam
pushad
print str$(eax), " is the process ID from GetProcessIdOfThread", 13, 10
popad
.endif
.if !eax
mov eax, lParam
.endif
pushad
print str$(eax), " is the process ID", 13, 10
popad
call FreeLibrary


When switching with Alt Tab to this window from my browser, I get this:

2236 is the thread ID
0 is the process ID from GetProcessIdOfThread  (which probably means thread=process)
2236 is the process ID


There is absolutely no process with ID 2236 :cool:
Title: Re: WM_ACTIVATEAPP problem
Post by: _japheth on May 27, 2022, 05:02:38 PM

I'm very likely the wrong person to "answer" a Windoze question, since I switched to other OSes long ago,

but I vaguely remember that there is a difference between a thread ID and a thread handle - they cannot be mixed because they are different animals.
Title: Re: WM_ACTIVATEAPP problem
Post by: jj2007 on May 27, 2022, 05:37:40 PM
Thanks, Andreas :thup:

QuoteWM_ACTIVATEAPP (https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-activateapp)

lParam

The thread identifier. If the wParam parameter is TRUE, lParam is the identifier of the thread that owns the window being deactivated. If wParam is FALSE, lParam is the identifier of the thread that owns the window being activated.

The numbers I see are always in the n....2500 range. These are IDs, not handles.

This is the first time I try to use WM_ACTIVATEAPP. It's not that important for me, but I wonder what can go wrong with such an old and well-documented message :rolleyes:
Title: Re: WM_ACTIVATEAPP problem
Post by: felipe on May 27, 2022, 10:26:35 PM
After reading a bit and looking your code maybe this can help you a bit:

Windows documentation says that GetProcessIdOfThread needs a handle to the thread, but you are passing to it a thread id. How you get this handle? You need to use OpenThread which, in one of its parameters expects a thread id. The return value of this last function (in case of success) will be the thread handle. Then use that one for the function GetProcessIdOfThread and you should end up with the process id.  :icon_idea:
Title: Re: WM_ACTIVATEAPP problem
Post by: jj2007 on May 27, 2022, 10:45:52 PM
Thanks, Felipe. What you write is correct, and I had not seen it. However, in practice I never used GetProcessIdOfThread simply because it always returned zero (and now you've told me why - it expects a handle, not an ID). So I took lParam instead, which clearly should be an "identifier". Knowing Microsoft, I wonder whether they mean "handle" when they write "identifier", but it's not very probable :sad:
Title: Re: WM_ACTIVATEAPP problem
Post by: felipe on May 27, 2022, 11:02:00 PM
I have done a little test program that shows that actually that info is correct  :thup:. Attached below. Here's the output:

Process ID: 0000000000000CA0

And below an image with the process id. (In hex ca0 = 3232).
Title: Re: WM_ACTIVATEAPP problem
Post by: felipe on May 27, 2022, 11:15:44 PM
Here with the more friendly indentation   :toothy::
; Program that shows the process id.

option casemap:none
include \masm64\include64\win64.inc
include \masm64\include64\kernel32.inc
includelib \masm64\lib64\kernel32.lib

.data
con_title byte "Process ID",0h
process_id byte "Process ID: ", 16 dup(0h)
input_buff qword 0h
chars_written qword 0h
chars_readed qword 0h

.code
start proc
      sub rsp,28h
      call GetCurrentThreadId
      mov r12,rax ; Thread ID.
      mov rcx,THREAD_QUERY_INFORMATION
      xor rdx,rdx
      mov r8,r12
      call OpenThread
      mov r13,rax ; Thread handle.
      mov rcx,r13
      call GetProcessIdOfThread
      mov rsi,rax ; Process ID.
      mov rcx,rsi
      lea rdx,process_id
      mov r8,sizeof process_id
      mov r9,16 ; 16 nibbles.
      call reg_value ; Get value of rsi.
      call FreeConsole ; Detach process of inherited console
      call AllocConsole ;  and create a new one.
      lea rcx,con_title
      call SetConsoleTitle
      mov rcx,STD_OUTPUT_HANDLE
      call GetStdHandle
      mov r15,rax ; Output handle.
      mov rcx,r15
      lea rdx,process_id
      mov r8,sizeof process_id
      lea r9,chars_written
      mov qword ptr[rsp+20h],NULL
      call WriteConsole
      mov rcx,STD_INPUT_HANDLE
      call GetStdHandle
      mov r15,rax ; Input handle.
      mov rcx,r15
      mov rdx,ENABLE_LINE_INPUT
      call SetConsoleMode
      mov rcx,r15
      lea rdx,input_buff
      mov r8,1 ; Read just the character CR.
      lea r9,chars_readed
      mov qword ptr[rsp+20h],NULL
      call ReadConsole
      xor rcx,rcx
      call ExitProcess
start endp

reg_value proc
          push rbp
          mov rbp,rsp
next_nibble:
          mov rsp,rcx
          and rcx,0fh ; Isolate lsb.
          cmp rcx,09h
          ja can_be_a
          or rcx,30h ; To ascii.
          dec r8
          mov [rdx+r8],cl
          dec r9
          and r9,r9
          jz all_done
          mov rcx,rsp
          shr rcx,4
          jmp next_nibble
can_be_a:
          cmp rcx,0ah
          jne can_be_b
          mov rcx,'A'
          dec r8
          mov [rdx+r8],cl
          dec r9
          and r9,r9
          jz all_done
          mov rcx,rsp
          shr rcx,4
          jmp next_nibble
can_be_b:
          cmp rcx,0bh
          jne can_be_c
          mov rcx,'B'
          dec r8
          mov [rdx+r8],cl
          dec r9
          and r9,r9
          jz all_done
          mov rcx,rsp
          shr rcx,4
          jmp next_nibble
can_be_c:
          cmp rcx,0ch
          jne can_be_d
          mov rcx,'C'
          dec r8
          mov [rdx+r8],cl
          dec r9
          and r9,r9
          jz all_done
          mov rcx,rsp
          shr rcx,4
          jmp next_nibble
can_be_d:
          cmp rcx,0dh
          jne can_be_e
          mov rcx,'D'
          dec r8
          mov [rdx+r8],cl
          dec r9
          and r9,r9
          jz all_done
          mov rcx,rsp
          shr rcx,4
          jmp next_nibble
can_be_e:
          cmp rcx,0eh
          jne is_f
          mov rcx,'E'
          dec r8
          mov [rdx+r8],cl
          dec r9
          and r9,r9
          jz all_done
          mov rcx,rsp
          shr rcx,4
          jmp next_nibble
is_f:
          mov rcx,'F'
          dec r8
          mov [rdx+r8],cl
          dec r9
          and r9,r9
          jz all_done
          mov rcx,rsp
          shr rcx,4
          jmp next_nibble
all_done:
          mov rsp,rbp
          pop rbp
          ret
reg_value endp
end