Kayaker
November 2nd, 2002, 10:39
Hi All,
A while back I added mouse wheel support to my Win98 Winhlp32.exe file, basically because I was tired of not being able to mouse scroll in the Win32 Programmers Reference. I thought this would make a good project, but then I found out the Win2K and above versions of winhlp32.exe had mouse wheel support already built in. Damn MS anyway for stealing my idea! ;-) Aha, then I realized W32Dasm doesn't have mouse wheel scroll capabilities either, so this has now become the target for this project.
Usually I build a patch directly in Softice with the a(ssemble) command, which allows me to test and modify it on the go, then dump the bytes and insert them into the file with a hex editor and/or rebuild it using HIEW. This time however I decided to try out Iczelion's Code Snippet Creator, and I must admit to being very impressed. So this is a combination project which can deal with code injection/patching as a whole, as well as learning how to use this nifty tool.
What we want to do is find a spot in the Windows messaging queue in W32Dasm where we can insert a jmp to our patch code. The patch code itself will contain the new code to test for and handle the WM_MOUSEWHEEL message. The messaging queue is where messages such as WM_COMMAND and others are processed. This is the first hurdle to overcome for those who have never delved into or patched this area before. Finding and recognizing this code and understanding roughly what it is doing is the first step. I'd recommend focussing on trying to find where WM_COMMAND itself is handled. This message is called, for one, when a Menu item is selected and has a constant value of 111h, so a BMSG breakpoint can be used to break on it. From the BMSG break there are techniques to trace directly to the start of the messaging queue. If you are unsure how, I would suggest as a start looking at the Menu Enabling Project we had some time ago and Clandestiny's tutorial (on the main site) that came out of that, the techniques are discussed in there.
Menu Enabling Project (http://www.woodmann.net/forum/showthread.php?threadid=126)
There are other messages you could use and other ways to find the proper code area, including deadlisting, keying in on recognizable message constants such as "111h" for example, but whatever works for you.
What I'll do is supply the MASM code snippet that I used to develop the patch, or you can develop your own. Most of what you need to know about handling WM_MOUSEWHEEL is in the Win32 Programmers Reference, or you can go to MSDN for more info. If you do use the Snippet Creator you will need MASM installed of course. This isn't a complete copy and paste, you'll need to change what needs to be changed to get the right hWnd and wParam values for the real target, plus W32Dasm is a little peculiar actually, so this patch isn't necessarily as easy as it might seem.
Without giving too much else away, here is a generalized snippet that I developed in a test listview app before turning it into a patch, change what you see fit. There are more sophisticated ways to handle WM_MOUSEWHEEL but this was sufficient for my purposes. Every scroll of the mouse wheel up or down advances the page 3 lines (set in the loop). If the shift key is also held down then it's a full page scroll, this is a bit of an improvement on the standard routine that I just personally like.
As for setting up and using Code Snippet Creator, if you decide to use it, the help file should be enough, but we can deal with problems if they arise. If you happen not to have a mouse with a wheel then you could always assign line/page scrolling functionality to W32Dasm with a hotkey instead (handle WM_KEYDOWN). If there are any questions don't be afraid to ask, there are many who can help with this. I know ZaiRoN has wanted to do a Code Snippet Creator project for a while
Good luck and have fun.
Cheers,
Kayaker
A while back I added mouse wheel support to my Win98 Winhlp32.exe file, basically because I was tired of not being able to mouse scroll in the Win32 Programmers Reference. I thought this would make a good project, but then I found out the Win2K and above versions of winhlp32.exe had mouse wheel support already built in. Damn MS anyway for stealing my idea! ;-) Aha, then I realized W32Dasm doesn't have mouse wheel scroll capabilities either, so this has now become the target for this project.
Usually I build a patch directly in Softice with the a(ssemble) command, which allows me to test and modify it on the go, then dump the bytes and insert them into the file with a hex editor and/or rebuild it using HIEW. This time however I decided to try out Iczelion's Code Snippet Creator, and I must admit to being very impressed. So this is a combination project which can deal with code injection/patching as a whole, as well as learning how to use this nifty tool.
What we want to do is find a spot in the Windows messaging queue in W32Dasm where we can insert a jmp to our patch code. The patch code itself will contain the new code to test for and handle the WM_MOUSEWHEEL message. The messaging queue is where messages such as WM_COMMAND and others are processed. This is the first hurdle to overcome for those who have never delved into or patched this area before. Finding and recognizing this code and understanding roughly what it is doing is the first step. I'd recommend focussing on trying to find where WM_COMMAND itself is handled. This message is called, for one, when a Menu item is selected and has a constant value of 111h, so a BMSG breakpoint can be used to break on it. From the BMSG break there are techniques to trace directly to the start of the messaging queue. If you are unsure how, I would suggest as a start looking at the Menu Enabling Project we had some time ago and Clandestiny's tutorial (on the main site) that came out of that, the techniques are discussed in there.
Menu Enabling Project (http://www.woodmann.net/forum/showthread.php?threadid=126)
There are other messages you could use and other ways to find the proper code area, including deadlisting, keying in on recognizable message constants such as "111h" for example, but whatever works for you.
What I'll do is supply the MASM code snippet that I used to develop the patch, or you can develop your own. Most of what you need to know about handling WM_MOUSEWHEEL is in the Win32 Programmers Reference, or you can go to MSDN for more info. If you do use the Snippet Creator you will need MASM installed of course. This isn't a complete copy and paste, you'll need to change what needs to be changed to get the right hWnd and wParam values for the real target, plus W32Dasm is a little peculiar actually, so this patch isn't necessarily as easy as it might seem.
Without giving too much else away, here is a generalized snippet that I developed in a test listview app before turning it into a patch, change what you see fit. There are more sophisticated ways to handle WM_MOUSEWHEEL but this was sufficient for my purposes. Every scroll of the mouse wheel up or down advances the page 3 lines (set in the loop). If the shift key is also held down then it's a full page scroll, this is a bit of an improvement on the standard routine that I just personally like.
Code:
; ListViewClassName db "SysListView32",0
; (example has nothing to do with W32Dasm but you may want
; to use a class name in your code)
.ELSEIF uMsg == WM_MOUSEWHEEL ; constant = 20Ah
; invoke FindWindowEx, hWnd, NULL, ADDR ListViewClassName, NULL
; WM_MOUSEWHEEL is sent to the Parent window, I needed the
; listview Child window for the SendMessage calls.
; This may not be the case with W32Dasm, check out what's
; happening! In any case, EAX is now the hWnd of the Listview
; itself (I think in W32Dasm it's a Listbox).
mov edx, wParam
mov ebx, edx
and ebx, 0ffffh
; LOWORD is returned in ebx, indicates if virtual key held down
sar edx, 16
; HIWORD is returned in edx, +ve value scroll up, -ve down
.IF SDWORD PTR edx < 0 ; Negative value of high-order word = wheel down
.if ebx == MK_SHIFT ; SHIFT key is down (0004h)
invoke SendMessage, eax, WM_VSCROLL, SB_PAGEDOWN, 0
.else
mov ebx, 3 ; scroll 3 lines for each wheel movement
.while ebx != 0
invoke SendMessage, eax, WM_VSCROLL, SB_LINEDOWN, 0
dec ebx
.endw
.endif
.ELSE ; Positive value of high-order word = wheel up
.if ebx == MK_SHIFT ; SHIFT key is down (0004h)
invoke SendMessage, eax, WM_VSCROLL, SB_PAGEUP, 0
.else
mov ebx, 3
.while ebx != 0
invoke SendMessage, eax, WM_VSCROLL, SB_LINEUP, 0
dec ebx
.endw
.endif
.ENDIF
.ENDIF
As for setting up and using Code Snippet Creator, if you decide to use it, the help file should be enough, but we can deal with problems if they arise. If you happen not to have a mouse with a wheel then you could always assign line/page scrolling functionality to W32Dasm with a hotkey instead (handle WM_KEYDOWN). If there are any questions don't be afraid to ask, there are many who can help with this. I know ZaiRoN has wanted to do a Code Snippet Creator project for a while

Good luck and have fun.
Cheers,
Kayaker