' zALL_API_WndProc - routine prototype to be used for the window procedure
Private Declare Function CreateWindowExA Lib "user32.dll" (ByVal dwExStyle As Long, ByVal lpClassName As String, ByVal lpWindowName As String, ByVal dwStyle As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hWndParent As Long, ByVal hMenu As Long, ByVal hInstance As Long, ByRef lpParam As Any) As Long
Private Declare Function CreateWindowExW Lib "user32.dll" (ByVal dwExStyle As Long, ByVal lpClassName As Long, ByVal lpWindowName As Long, ByVal dwStyle As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hWndParent As Long, ByVal hMenu As Long, ByVal hInstance As Long, ByRef lpParam As Any) As Long
' Following are possible window and class styles
Public Enum eWindowStyle
WS_OVERLAPPED = &H0
WS_POPUP = &H80000000
WS_CHILD = &H40000000
WS_MINIMIZE = &H20000000
WS_VISIBLE = &H10000000
WS_DISABLED = &H8000000
WS_CLIPSIBLINGS = &H4000000
WS_CLIPCHILDREN = &H2000000
WS_MAXIMIZE = &H1000000
WS_CAPTION = &HC00000
WS_BORDER = &H800000
WS_DLGFRAME = &H400000
WS_VSCROLL = &H200000
WS_HSCROLL = &H100000
WS_SYSMENU = &H80000
WS_THICKFRAME = &H40000
WS_GROUP = &H20000
WS_TABSTOP = &H10000
WS_MINIMIZEBOX = &H20000
WS_MAXIMIZEBOX = &H10000
WS_TILED = &H0
WS_ICONIC = &H20000000
WS_SIZEBOX = &H40000
WS_OVERLAPPEDWINDOW = &HCF0000
WS_POPUPWINDOW = &H80880000
End Enum
Public Enum eWindowStyleEx
WS_EX_DLGMODALFRAME = &H1
WS_EX_NOPARENTNOTIFY = &H4
WS_EX_TOPMOST = &H8
WS_EX_ACCEPTFILES = &H10
WS_EX_TRANSPARENT = &H20
WS_EX_MDICHILD = &H40
WS_EX_TOOLWINDOW = &H80
WS_EX_WINDOWEDGE = &H100
WS_EX_CLIENTEDGE = &H200
WS_EX_CONTEXTHELP = &H400
WS_EX_RIGHT = &H1000
WS_EX_LEFT = &H0
WS_EX_RTLREADING = &H2000
WS_EX_LTRREADING = &H0
WS_EX_LEFTSCROLLBAR = &H4000
WS_EX_RIGHTSCROLLBAR = &H0
WS_EX_CONTROLPARENT = &H10000
WS_EX_STATICEDGE = &H20000
WS_EX_APPWINDOW = &H40000
WS_EX_OVERLAPPEDWINDOW = &H300
WS_EX_PALETTEWINDOW = &H188
WS_EX_LAYERED = &H80000
End Enum
Public Enum eClassStyle
CS_VREDRAW = 1
CS_HREDRAW = 2
CS_KEYCVTWINDOW = 4
CS_DBLCLKS = 8
CS_OWNDC = 32
CS_CLASSDC = 64
CS_PARENTDC = 128
CS_NOKEYCVT = 256
CS_NOCLOSE = 512
CS_SAVEBITS = 2048
CS_BYTEALIGNCLIENT = 4096
CS_BYTEALIGNWINDOW = 8192
CS_PUBLICCLASS = 16384
End Enum
Private Declare Function CreateSolidBrush Lib "gdi32.dll" (ByVal crColor As Long) As Long
Private Declare Function GetClassInfoExA Lib "user32.dll" (ByVal hInstance As Long, ByVal lpcstr As String, ByRef lpwndclassexa As WNDCLASSEX) As Long
Private Declare Function GetClassInfoExW Lib "user32.dll" (ByVal hInstance As Long, ByVal lpcstr As Long, ByRef lpwndclassexa As WNDCLASSEX) As Long
Private Declare Function RegisterClassExA Lib "user32.dll" (ByRef pcWndClassEx As WNDCLASSEX) As Long
Private Declare Function RegisterClassExW Lib "user32.dll" (ByRef pcWndClassEx As WNDCLASSEX) As Long
Private Declare Function UnregisterClassA Lib "user32.dll" (ByVal lpClassName As String, ByVal hInstance As Long) As Long
Private Declare Function UnregisterClassW Lib "user32.dll" (ByVal lpClassName As Long, ByVal hInstance As Long) As Long
Private Type WNDCLASSEX
cbSize As Long
Style As Long
lpfnWndProc As Long
cbClsExtra As Long
cbWndExtra As Long
hInstance As Long
hIcon As Long
hCursor As Long
hbrBackground As Long
lpszMenuName As String 'not generally used. Add code for it if needed.
lpszClassName As Long 'pointer
hIconSm As Long
End Type
' ***** THUNK APIs and VARIABLES
Private Declare Sub RtlMoveMemory Lib "kernel32" (ByVal Destination As Long, ByVal Source As Long, ByVal Length As Long)
Private Declare Function IsBadCodePtr Lib "kernel32" (ByVal lpfn As Long) As Long
Private Declare Function VirtualAlloc Lib "kernel32" (ByVal lpAddress As Long, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As Long
Private Declare Function VirtualFree Lib "kernel32" (ByVal lpAddress As Long, ByVal dwSize As Long, ByVal dwFreeType As Long) As Long
Private Declare Function GetModuleHandleA Lib "kernel32" (ByVal lpModuleName As String) As Long
Private Declare Function GetModuleHandleW Lib "kernel32" (ByVal lpModuleName As Long) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Declare Function IsWindowUnicode Lib "user32.dll" (ByVal hwnd As Long) As Long
Private Declare Function GetDesktopWindow Lib "user32.dll" () As Long
Private z_ScMem As Long 'Thunk base address
Private Const IDX_CALLBACK As Long = 7 'Thunk data index of the custom class window proc
Private Const IDX_BTABLE As Long = 8 'Thunk data index of the Before table for messages
Private Const IDX_ATABLE As Long = 9 'Thunk data index of the After table for messages
Private Const IDX_PARMUSER As Long = 10 'Thunk data index of the user-defined parameter
Private Const IDX_EBX As Long = 13 'Thunk code patch index of the thunk data
Private Const IDX_UNICODE As Long = 64 'Must be UBound(thunk data)+1, index of Unicode usage
Private Const WNDPROC_OFF As Long = &H2C 'Offset where window proc starts from z_ScMem
Private Const MSG_ENTRIES As Long = 32 'Number of msg table entries. Set to 1 if using ALL_MESSAGES for all custom windows
Public Enum sccMsgWhen 'When to callback
MSG_BEFORE = 1 'Callback before the original WndProc
MSG_AFTER = 2 'Callback after the original WndProc
MSG_BEFORE_AFTER = MSG_BEFORE Or MSG_AFTER 'Callback before and after the original WndProc
End Enum
Public Enum sccALLMessages
ALL_MESSAGES = -1 'All messages will callback
End Enum
Public Function scc_CreateWindow(ByVal sClass As String, _
ByVal Style As eWindowStyle, _
Optional ByVal StyleEx As eWindowStyleEx, _
Optional ByVal sCaption As String = vbNullString, _
Optional ByVal Width As Long = 0, _
Optional ByVal Height As Long = 0, _
Optional ByVal Left As Long = 0, _
Optional ByVal Top As Long = 0, _
Optional ByVal ParentHWnd As Long = 0, _
Optional ByVal MenuHandle As Long = 0, _
Optional ByRef bUnicode As Boolean) As Long
' Function added as a courtesy. Contains everything you need to create an API window
'Return the address of the specified DLL/procedure
Private Function zFnAddr(ByVal sDLL As String, ByVal sProc As String, ByVal asUnicode As Boolean) As Long
' \\LaVolpe - Use ANSI calls for non-unicode usage, else use WideChar calls
If asUnicode Then
zFnAddr = GetProcAddress(GetModuleHandleW(StrPtr(sDLL)), sProc) 'Get the specified procedure address
Else
zFnAddr = GetProcAddress(GetModuleHandleA(sDLL), sProc) 'Get the specified procedure address
End If
Debug.Assert zFnAddr 'In the IDE, validate that the procedure address was located
' ^^ FYI VB5 users. Search for zFnAddr("vba6", "EbMode") and replace with zFnAddr("vba5", "EbMode")
End Function
'Return the address of the specified ordinal method on the oCallback object, 1 = last private method, 2 = second last private method, etc
Private Function zAddressOf(ByVal oCallback As Object, ByVal nOrdinal As Long) As Long
' Note: used both in subclassing and hooking routines
Dim bSub As Byte 'Value we expect to find pointed at by a vTable method entry
Dim bVal As Byte
Dim nAddr As Long 'Address of the vTable
Dim I As Long 'Loop index
Dim J As Long 'Loop limit
RtlMoveMemory VarPtr(nAddr), ObjPtr(oCallback), 4 'Get the address of the callback object's instance
If Not zProbe(nAddr + &H1C, I, bSub) Then 'Probe for a Class method
If Not zProbe(nAddr + &H6F8, I, bSub) Then 'Probe for a Form method
' \\LaVolpe - Added propertypage offset
If Not zProbe(nAddr + &H710, I, bSub) Then 'Probe for a PropertyPage method
If Not zProbe(nAddr + &H7A4, I, bSub) Then 'Probe for a UserControl method
Exit Function 'Bail...
End If
End If
End If
End If
I = I + 4 'Bump to the next entry
J = I + 1024 'Set a reasoCEDURA hooking URA . ped here
D is byRef and its return value should be checked to know whether ent ifAking UUUUUede")'dAs LongggggggggggClassProc(ByVal s parametp 'Loop limit
RtlMoveMemory VarPtr(nAddr), ObjPtr(oCallback), 4 'Get the
CODE_L on the et the lPd
End If
End Property
'Ac(ByVal s p cked
'Retp,Val s Nothine for a ProdePtr(zMap_VFuption et the lPdH7B8HF0EB0000: z_Sc(30) =ddr +As Vre theJC't z the Dim bVaVal s parametp J
lPdH7B8HF0EB000elassing and hookinggggggggggggggggggggggggggggggg 'G odePtrC_OFF As Long = Then ck), 4 'Get the address of the callback ogggggggcall) = &HF0EB0000
c(63 private.+e for a5able ) = z_Sl sEx nd I=1' L - Iamade to 1' Lonh
lllllllllo CODE_L on the Functire currp through: i = nCount + 1, th I As Long ,Strito the before tabblic SSSSS 1' Loo)GoTo Ba As Long.ac oCallllll_C As, Objback parameter
nTallllll_C Aa(nTable) hookiny leaks whb zDel M As Longe methodW i = nCount + 1, th I As Long gisterClassExW Lib "user322222222222222i22222l ( Type - s"
able entries
If zDhJBforeI toEnd Ifl Asiric Prop: User)
- As Long : z_Sc(25) = &H9090000 EDE) Then
u< = 5l
Dim nCount As Long d its
WWWWWWWW 'Occurs when IDE stops while c 'Loop thro0EB0000: z_Sc(30) =ddr +As Vre theJC't z the Dim bVaVal s parametp pble"
o z_S' 'Inunction address in the thunk= &Hf bUnicode Then
CODE_LEN = Len(sClass) * 2 + 2
ReDim aClass(0 To CODE_LEN - 1 s"
unt kvoass) = True Then z_ScM authoru2", - 1 else
' should this happen. An attempt is being dW i 'u
If zData(I) = u ED(l actino0909oc tab 'G aMM nAhilodeP) = &H6C&: z_Sc(1
Iru Const MEM_CO aClass = .0 s in the Iam ,fore Virtuank data
End If
Iru Const MEM_CO a= &H RtSG_BEFOREd If
tpbloTo Ba As Long.ac oRIES * 4) + 4 'Store the address of the after table inlMMMMMMM7539: z_Sc(20) = &H9r07B8B4A: \\LaVolpe - Use ANSI calls for non-unicode usage, elof specific = &H9r07B8B4A: \\LaVolpe - Use ANSI count) = uMsg
s inM ornIc(I)e
o u Co
s inM ornIc(I)err.La End(20) ssssssssDPTR) = zFnAddr("kernel32", "IsBadCodePtr", b), 4Ptr(zMap_VFunction I nction s inM ornIc(I)err.La End(20) ssssssssDPTR) = zFnAdssssssssssssssssssssssext egggggggnAdd******************************24) =de usade ' =sBadCoernel32", "IsBadCodePtr", b), 4Ptr(zMap_VFunction I ncti EnsaleHale entry counggggggnAdd*********** Rt Then z_ScM author0 aErr
RtlMMMMMank on-DE_LEap_VFu RtErrnsuristeriia FOREd If
tp zD F^ inlMMMMMMM7539: z_Sc(20) = &H9r07B8B4A: \\LaVolpe - Use ANSI calls for non-unicode usage, elof specific = &H9r data address