scrollfix source code

The code demonstrate easy injection of code using system wide hook, and windows subclassing.
All the main program has to do is load the DLL, the rest is done by the DLL itself.

The part of  the actual fix is missing, they aint getting it free from me.

#include "stdafx.h"

#include <map>
#include
#include

// NOTE: ALL members of the shared section must be initialized
#pragma data_seg(".shareddata")
DWORD dwAppProcessId = 0; // accessible across all processes
#pragma data_seg()
#pragma comment(linker, "/section:.shareddata,rws")

HHOOK hook = 0; // used by application
bool active = false; // true for paltal, false for any other process

bool Hook(HINSTANCE hInstance);
void Unhook();

void subclass_all();
void unsubclass_all();

int WINAPI DllMain(HINSTANCE hInst, DWORD fwdreason, LPVOID /*lpvReserved*/)
{
switch(fwdreason)
{ /* reason */
//**********************************************
// PROCESS_ATTACH
//**********************************************
case DLL_PROCESS_ATTACH:
// first module that loads (application)
// enfotce dll in application directory
TCHAR mmpath[MAX_PATH];
if (dwAppProcessId == 0) {
TCHAR mpath[MAX_PATH];
if (GetModuleFileName(hInst, mpath, sizeof(mpath)) && GetModuleFileName(NULL, mmpath, sizeof(mmpath))) {
*wcsrchr(mpath, '\\') = '';
*wcsrchr(mmpath, '\\') = '';
if (lstrcmpi(mpath, mmpath) == 0) {
if (!Hook(hInst))
return FALSE;
dwAppProcessId = GetCurrentProcessId();
}
} else
return FALSE;
// ignore any process other than paltak
} else if (GetModuleFileName(NULL, mmpath, sizeof(mmpath)) &&
lstrcmpi(wcsrchr(mmpath, '\\')+1, TEXT("paltalk.exe")) == 0) {
if (!active) { // should never be true
subclass_all();
active = true;
}
}
break;

//**********************************************
// PROCESS_DETACH
//**********************************************
case DLL_PROCESS_DETACH:
if (hook != NULL) // application exists - unhook
Unhook();
else if (active) { // only for paltalk active = true
active = false;
unsubclass_all();
}
} /* reason */
return TRUE;
}

static LRESULT CALLBACK ShellProc(int nCode, WPARAM wParam, LPARAM lParam);
bool Hook(HINSTANCE hInstance)
{
if (hook == NULL)
hook = SetWindowsHookEx(WH_SHELL, ShellProc, hInstance, 0);
return (hook != NULL);
}

void Unhook()
{
if (hook != NULL)
UnhookWindowsHookEx(hook);
hook = NULL;
}

void subclass(HWND hwnd);
void unsubclass(HWND hwnd);
static
LRESULT CALLBACK ShellProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode < 0) // required according to documentation
return CallNextHookEx(hook, nCode,wParam, lParam);

if (active) { // this is paltalk
switch (nCode) {
case HSHELL_WINDOWCREATED: // subclass newly oppened chatrooms
subclass((HWND)wParam);
break;
case HSHELL_WINDOWDESTROYED:// unsubclass closed rooms
unsubclass((HWND)wParam);
break;
}
}
// Pass the message on to the next hook
return CallNextHookEx(hook, nCode, wParam, lParam);
}

/*
Internal lib stuff
*/
typedef std::pair<hwnd,bool> enum_param;

// finds room control for chatrooms windows only
BOOL CALLBACK FindControlsRoomProc(HWND hwnd, LPARAM lParam) {
int ctlID = GetDlgCtrlID(hwnd);
enum_param *ctl = (enum_param*) lParam;
switch (ctlID) {
case 0x6FD:
if (IsWindowVisible(hwnd)) // user list is only visable in chatrooms
ctl->second = true;
break;
case 0xCA:
ctl->first = hwnd; // room text control
break;
case 0xCB:
break;
}
return TRUE;
}

// used by chatroom text WndProc for the fix
struct POS {
// code removed
};

// subclassed chatroom text control data
struct subctl {
subctl(WNDPROC prev)
{
this->prev = prev;
}
WNDPROC prev;
POS pos;
};

typedef std::map<hwnd,hwnd> subwins; // chat windows with subclassed controls
typedef std::map<hwnd,subctl> subctls; // subclassed controls

subwins windows;
subctls controls;

LRESULT APIENTRY RoomTexcProc(HWND, UINT, WPARAM, LPARAM);
void subclass(HWND hwnd)
{
TCHAR str[128];
// subclass is called blindly, check it is a chatroom window
if (GetClassName(hwnd, str, sizeof(str)) == 0)
return;
if (lstrcmp(str, L"DlgGroupChat Window Class"))
return;
enum_param ctl;
EnumChildWindows(hwnd, FindControlsRoomProc, LPARAM(&ctl));
if (ctl.second && ctl.first != NULL) {
assert( windows.find(ctl.first) == windows.end() );
// install subclass WndProc
WNDPROC prev = (WNDPROC) SetWindowLongPtr(ctl.first, GWL_WNDPROC, LONG(RoomTexcProc));
// save subclassed chatroom window
windows.insert(subwins::value_type(hwnd, ctl.first));
// save subclassed control
controls.insert(subctls::value_type(ctl.first, subctl(prev)));
}
}

BOOL CALLBACK SubclassProc(HWND hwnd, LPARAM lParam)
{
subclass(hwnd);
return TRUE;
}

void subclass_all()
{
EnumThreadWindows(GetCurrentThreadId(), SubclassProc, 0);
}

void unsubclass(subwins::const_iterator it)
{
subctls::const_iterator cit = controls.find(it->second);
assert (cit != controls.end() );
// restore original WndProc
SetWindowLongPtr(cit->first, GWL_WNDPROC, LONG(cit->second.prev));
// remove window and controll from lists
controls.erase(cit);
windows.erase(it);
}

void unsubclass(HWND hwnd)
{
subwins::const_iterator it = windows.find(hwnd);
     // unsubclass is called blindly, check if this window in our list
if (it != windows.end())
unsubclass(it);
}

void unsubclass_all()
{
while (!windows.empty()) {
unsubclass(windows.begin());
}
}

LRESULT
APIENTRY RoomTexcProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
subctls::iterator it = controls.find(hwnd); // find control data in subclassed controlls list
WNDPROC wndprocPrev = it->second.prev;
POS *pos;

switch (uMsg) {
// fix code gremoved
}
// call original WndProc
return CallWindowProc(wndprocPrev, hwnd, uMsg, wParam, lParam);
}

 

2 thoughts on “scrollfix source code

Leave a Reply

You must Register or Login to comment on scrollfix source code