00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "GASPilotDLL.h"
00017
00018 #define CAT_WM_FASTER WM_USER + 555
00019 #define CAT_WM_SLOWER WM_USER + 556
00020
00021 unsigned int _stdcall InjectedThreadFunc(void *param);
00022
00023 HANDLE gThreadHandle = 0;
00024 HANDLE gExitEvent = 0;
00025 HMODULE gInstance = 0;
00026 int gPID = 0;
00027 wchar_t gEventName[64];
00028
00029 BOOL WINAPI DllMain( HINSTANCE hinstDLL,
00030 DWORD fdwReason,
00031 LPVOID lpvReserved)
00032 {
00033 switch (fdwReason)
00034 {
00035 case DLL_PROCESS_ATTACH:
00036 {
00037 gPID = _getpid();
00038 gInstance = hinstDLL;
00039 swprintf(gEventName,64,L"GASPilotDLL_%d",gPID);
00040 gExitEvent = ::CreateEvent(0,TRUE,0,gEventName);
00041
00042
00043 unsigned int threadId = 0;
00044 gThreadHandle = (HANDLE)_beginthreadex(0,0,InjectedThreadFunc,0,0,&threadId);
00045 ::OutputDebugString(L"GASPilotDLL injected.\n");
00046 }
00047 break;
00048
00049 case DLL_PROCESS_DETACH:
00050
00051
00052 if (gExitEvent)
00053 {
00054 ::CloseHandle(gExitEvent);
00055 gExitEvent = 0;
00056 }
00057 if (gThreadHandle)
00058 {
00059 ::CloseHandle(gThreadHandle);
00060 }
00061 ::OutputDebugString(L"GASPilotDLL exiting.\n");
00062 break;
00063 }
00064
00065 return TRUE;
00066 }
00067
00068 unsigned int _stdcall InjectedThreadFunc(void *param)
00069 {
00070 ::OutputDebugString(L"Starting InjectedThread.\n");
00071 GASPilotDLL* gp = new GASPilotDLL();
00072 gp->Run();
00073 delete gp;
00074 ::OutputDebugString(L"Exiting InjectedThread.\n");
00075 ::FreeLibraryAndExitThread(gInstance,-1);
00076 return 0;
00077 }
00078
00079
00080 extern "C"
00081 {
00082 void* gPassedData = 0;
00083 unsigned int gPassedDataLen = 0;
00084 void _declspec(dllexport) UnpatchProcess(void* passData,
00085 unsigned int passDataLen,
00086 void* startLoc,
00087 unsigned int patchSize,
00088 void* hostBuffer,
00089 unsigned int hostProcId)
00090 {
00091
00092
00093
00094 HANDLE hostProcess = ::OpenProcess(PROCESS_ALL_ACCESS,
00095 FALSE,
00096 hostProcId);
00097 if (hostProcess != 0)
00098 {
00099 DWORD amountRead = 0;
00100 ::ReadProcessMemory(hostProcess,hostBuffer,startLoc,patchSize,&amountRead);
00101 if (passDataLen && passData)
00102 {
00103 gPassedDataLen = passDataLen;
00104 gPassedData = new BYTE[passDataLen];
00105 ::ReadProcessMemory(hostProcess,passData,gPassedData,passDataLen,&amountRead);
00106 }
00107 CloseHandle(hostProcess);
00108 }
00109
00110
00111 wchar_t eventName[64];
00112 wsprintf(eventName,L"UnpatchProcess_%d",hostProcId);
00113 HANDLE waitEvent = ::OpenEvent(GENERIC_READ|GENERIC_WRITE,FALSE,eventName);
00114 if (waitEvent != 0)
00115 {
00116 ::SetEvent(waitEvent);
00117 CloseHandle(waitEvent);
00118 }
00119
00120
00121 __asm
00122 {
00123 mov esp,ebp
00124 pop ebp
00125 add esp,0x1c
00126 popfd
00127 popad
00128 ret
00129 }
00130 }
00131 }
00132
00133 GASPilotDLL::GASPilotDLL()
00134 {
00135 fSpeed = 1.00;
00136 fExecCap = 0;
00137 fTimeWarp = 0;
00138 fOverlayDX9 = 0;
00139 fOverlayGL = 0;
00140 fSpeedImg = 0;
00141 fSlowImg = 0;
00142 fFastImg = 0;
00143 fSpeedImg = 0;
00144
00145 ::GetModuleFileName(0,fHostApp.GetUnicodeBuffer(1024),1023);
00146 fHostApp.ReleaseBuffer();
00147
00148 ::GetModuleFileName(gInstance,fDLLPath.GetUnicodeBuffer(1024),1023);
00149 fDLLPath.ReleaseBuffer();
00150 fBasePath = fDLLPath.GetDriveDirectory();
00151 fSlowImgPath = fBasePath;
00152 fSlowImgPath << L"Overlays\\GameSpeed_e.png";
00153 fFastImgPath = fBasePath;
00154 fFastImgPath << L"Overlays\\GameSpeed_f.png";
00155
00156 fFastImg = 0;
00157 fSlowImg = 0;
00158
00159 CATStreamFile *imgStream = new CATStreamFile();
00160 CATResult result = imgStream->Open(fSlowImgPath,CATStream::READ_ONLY);
00161 if (CATSUCCEEDED(result))
00162 {
00163 result = CATImage::Load(imgStream,fSlowImg);
00164 imgStream->Close();
00165 }
00166 if (CATFAILED(result))
00167 {
00168 ::OutputDebugString(L"Failed to load speed image");
00169 ::OutputDebugString(fSlowImgPath);
00170 }
00171
00172 result = imgStream->Open(fFastImgPath,CATStream::READ_ONLY);
00173 if (CATSUCCEEDED(result))
00174 {
00175 result = CATImage::Load(imgStream,fFastImg);
00176 imgStream->Close();
00177 }
00178
00179 if (CATFAILED(result))
00180 {
00181 ::OutputDebugString(L"Failed to load speed image");
00182 ::OutputDebugString(fFastImgPath);
00183 }
00184
00185 delete imgStream;
00186 }
00187
00188 GASPilotDLL::~GASPilotDLL()
00189 {
00190 if (fOverlayDX9)
00191 fOverlayDX9->RestoreAll();
00192
00193 if (fTimeWarp)
00194 fTimeWarp->RestoreAll();
00195
00196 if (fExecCap)
00197 fExecCap->RestoreAll();
00198
00199 if (fOverlayGL)
00200 fOverlayGL->RestoreAll();
00201
00202 delete fOverlayDX9;
00203 fOverlayDX9 = 0;
00204
00205 delete fTimeWarp;
00206 fTimeWarp = 0;
00207
00208 delete fExecCap;
00209 fExecCap = 0;
00210
00211 delete fOverlayGL;
00212 fOverlayGL = 0;
00213
00214 if (fSpeedImg)
00215 CATImage::ReleaseImage(fSpeedImg);
00216 if (fFastImg)
00217 CATImage::ReleaseImage(fFastImg);
00218 if (fSlowImg)
00219 CATImage::ReleaseImage(fSlowImg);
00220 }
00221
00222 void GASPilotDLL::Run()
00223 {
00224 CATUInt32 hookFlags = this->CheckHooks();
00225
00226
00227 if (hookFlags & CATHook_Exec)
00228 {
00229 fExecCap = new CATInjectionPropagate(fDLLPath);
00230 fExecCap->HookFunctions();
00231 }
00232
00233 if (hookFlags & CATHook_OGL)
00234 {
00235 fOverlayGL = new CATOverlayOpenGL();
00236 fOverlayGL->HookFunctions();
00237 }
00238
00239 if (hookFlags & CATHook_DX9)
00240 {
00241 fOverlayDX9 = new CATOverlayDirect3D9();
00242 fOverlayDX9->HookFunctions();
00243 }
00244
00245 if (hookFlags & CATHook_Time)
00246 {
00247 fTimeWarp = new CATTimeWarp();
00248 fTimeWarp->HookFunctions();
00249 }
00250
00251
00252 CATFloat32 speed = 1.0f;
00253 CATInt32 logoWidth = 60;
00254
00255 if (fTimeWarp)
00256 fTimeWarp->GetSpeed();
00257
00258 CATRect rect(0,0,360,50);
00259 if (fFastImg)
00260 {
00261 fOverlayDX9->SetOverlayImage(fFastImg,rect,1024,768);
00262 fOverlayGL->SetOverlayImage(fFastImg,rect,1024,768);
00263 }
00264
00265
00266
00267 WNDCLASS msgWndClass;
00268 memset(&msgWndClass,0,sizeof(msgWndClass));
00269 HINSTANCE instance = gInstance;
00270 msgWndClass.style = 0;
00271 msgWndClass.lpfnWndProc = (WNDPROC)EventMsgProc;
00272 msgWndClass.cbClsExtra = 0;
00273 msgWndClass.cbWndExtra = 0;
00274 msgWndClass.hInstance = instance;
00275 msgWndClass.hIcon = 0;
00276 msgWndClass.hbrBackground = 0;
00277 msgWndClass.lpszMenuName = 0;
00278 msgWndClass.lpszClassName = L"GASPilotDLLWnd";
00279 ATOM classAtom = RegisterClass(&msgWndClass);
00280 ::RegisterClass(&msgWndClass);
00281
00282 fMsgWnd = ::CreateWindowEx(0,L"GASPilotDLLWnd",L"GASPilotMsgs",0,0,0,0,0,0,0,gInstance,this);
00283
00284
00285
00286 for (; ;)
00287 {
00288
00289 DWORD waitResult = MsgWaitForMultipleObjects(1,
00290 &gExitEvent,
00291 FALSE,
00292 150,
00293 QS_ALLINPUT);
00294
00295 if (waitResult == WAIT_OBJECT_0)
00296 {
00297 break;
00298 }
00299 else if (WAIT_TIMEOUT == waitResult)
00300 {
00301 CheckKeys();
00302 }
00303 else
00304 {
00305 MSG msg;
00306 while (PeekMessage(&msg, fMsgWnd, 0, 0, PM_REMOVE))
00307 {
00308 CheckKeys();
00309 TranslateMessage(&msg);
00310 DispatchMessage(&msg);
00311 }
00312 }
00313 }
00314
00315 DestroyWindow(fMsgWnd);
00316 UnregisterClass(L"GASPilotDLLWnd",gInstance);
00317
00318 }
00319
00320 LRESULT CALLBACK GASPilotDLL::EventMsgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
00321 {
00322 GASPilotDLL* pilot = 0;
00323
00324 if (message == WM_CREATE)
00325 {
00326 LPCREATESTRUCT lpc = (LPCREATESTRUCT)lParam;
00327 SetWindowLong(hWnd,GWL_USERDATA,PtrToUlong(lpc->lpCreateParams));
00328 SetWindowPos(hWnd,0,0,0,0,0,SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOZORDER|SWP_NOSIZE);
00329 pilot = (GASPilotDLL*)lpc->lpCreateParams;
00330 }
00331 else
00332 {
00333 pilot = (GASPilotDLL*)(ULONG_PTR)GetWindowLong(hWnd,GWL_USERDATA);
00334 }
00335
00336 switch (message)
00337 {
00338 case CAT_WM_SLOWER:
00339 pilot->OnSlower();
00340 break;
00341 case CAT_WM_FASTER:
00342 pilot->OnFaster();
00343 default:
00344 break;
00345 }
00346
00347 return DefWindowProc(hWnd,message,wParam,lParam);
00348 }
00349
00350 void GASPilotDLL::OnFaster()
00351 {
00352 fSpeed += 0.05f;
00353 UpdateSpeed();
00354 }
00355 void GASPilotDLL::OnSlower()
00356 {
00357 fSpeed -= 0.05f;
00358 UpdateSpeed();
00359 }
00360
00361 void GASPilotDLL::OnFast()
00362 {
00363 fSpeed = 1.0f;
00364 UpdateSpeed();
00365 }
00366 void GASPilotDLL::OnSlow()
00367 {
00368 fSpeed = 0.4f;
00369 UpdateSpeed();
00370 }
00371
00372 void GASPilotDLL::UpdateSpeed()
00373 {
00374 if (fSpeed > 1.0f)
00375 fSpeed = 1.0f;
00376 if (fSpeed < 0.2f)
00377 fSpeed = 0.2f;
00378
00379 if (fFastImg && fSlowImg)
00380 {
00381 CATImage* newSpeedImage = 0;
00382 CATImage::CopyImage(fSlowImg,newSpeedImage);
00383
00384 CATRect rect(0,0,360,50);
00385
00386 if (newSpeedImage)
00387 {
00388 newSpeedImage->Overlay(fFastImg,0,0,0,0,60 + (fFastImg->Width()-60)*fSpeed,fFastImg->Height());
00389 if (fOverlayDX9)
00390 fOverlayDX9->SetOverlayImage(newSpeedImage,rect,1024,768);
00391 if (fOverlayGL)
00392 fOverlayGL->SetOverlayImage(newSpeedImage,rect,1024,768);
00393 }
00394
00395 if (fSpeedImg != 0)
00396 CATImage::ReleaseImage(fSpeedImg );
00397 fSpeedImg = newSpeedImage;
00398 }
00399
00400 CATString speedStr;
00401 speedStr.Format(L"Setting speed to %f\n",fSpeed);
00402 ::OutputDebugString(speedStr);
00403
00404 if (fTimeWarp)
00405 fTimeWarp->SetSpeed(fSpeed);
00406
00407 ::InvalidateRect(::GetForegroundWindow(),0,FALSE);
00408 }
00409
00410 CATUInt32 GASPilotDLL::CheckHooks()
00411 {
00412 if (fHostApp.IsEmpty())
00413 return CATHook_All;
00414
00415
00416
00417 CATString appName = fHostApp.GetFilenameNoExt();
00418 if (0 == appName.CompareNoCase(L"steam"))
00419 {
00420 return CATHook_None;
00421 }
00422
00423 return CATHook_All;
00424 }
00425
00426 void GASPilotDLL::CheckKeys()
00427 {
00428 bool nextDown = (0x8000 & GetAsyncKeyState(VK_NEXT));
00429 bool prevDown = (0x8000 & GetAsyncKeyState(VK_PRIOR));
00430 bool f13 = (0x8000 & GetAsyncKeyState(VK_F13));
00431 bool f14 = (0x8000 & GetAsyncKeyState(VK_F14));
00432
00433 if (nextDown)
00434 {
00435 this->OnSlower();
00436 }
00437
00438 if (prevDown)
00439 {
00440 this->OnFaster();
00441 }
00442
00443 if (f13)
00444 this->OnSlow();
00445
00446 if (f14)
00447 this->OnFast();
00448 }