Game Accessibility Library logo SourceForge.net Logo
Game Accessibility Suite: GASPilot/GASPilot.cpp Source File

GASPilot.cpp

Go to the documentation of this file.
00001 /// \file GASPilot.cpp
00002 /// \brief GASPilot game/utility launcher
00003 /// \ingroup GASPilot
00004 ///
00005 /// This utility launches games with the various subutilities.
00006 ///
00007 /// Copyright (c) 2007-2008 by Michael Ellison.
00008 /// See COPYING.txt for the \ref gaslicense License (MIT License).
00009 ///
00010 // $Author: mikeellison $
00011 // $Date: 2008-02-01 03:19:21 -0600 (Fri, 01 Feb 2008) $
00012 // $Revision:   $
00013 // $NoKeywords: $
00014 
00015 #include "GASPilot.h"
00016 #include "GASPilotGuiFactory.h"
00017 #include "CATWindow.h"
00018 #include "CATAppButton.h"
00019 #include "CATEventDefs.h"
00020 #include "CATFileSystem.h"
00021 
00022 #include <psapi.h>
00023 /// App construct - requires you to specify a runmode in the 
00024 /// constructor.
00025 ///
00026 /// \param runMode - current runmode. See CATRunMode
00027 ///
00028 GASPilot::GASPilot(CATINSTANCE appInstance, CATRunMode runMode, const CATString& appName) 
00029 : CATApp(appInstance, runMode, appName)
00030 {
00031     fSteamThread    = 0;
00032     fControllerMenu = 0;
00033     fMappingMenu    = 0;
00034     fWindow         = 0;
00035     fInjectWindow   = 0;
00036     fCfgWindow      = 0;
00037     fMapper = new GASProtoMapper();
00038 }
00039 
00040 GASPilot::~GASPilot()
00041 {
00042     delete fMapper;
00043 }
00044 
00045 CATResult GASPilot::OnStart()
00046 {
00047     CATResult result = CAT_SUCCESS;
00048     CATString skinPath = this->GetSkinDir();
00049     skinPath << "Skin.xml";
00050 
00051     CATString skinDir, skinFile;
00052     this->fGlobalFileSystem->SplitPath(skinPath, skinDir, skinFile);
00053     this->fGUIFactory = new GASPilotGuiFactory(skinDir,skinPath);
00054 
00055     if (CATFAILED(result = this->LoadSkin(skinPath)))
00056     {
00057         return result;
00058     }
00059 
00060     if (result != CAT_SUCCESS)
00061     {
00062         this->DisplayError(result);
00063     }
00064         
00065     result = fSkin->OpenWindow(L"GASPilot", fWindow);
00066     
00067     // Snag control ptr's, if available
00068     if (fWindow)
00069     {
00070         fMappingMenu    = (CATMenu*)  fWindow->FindControlAndVerify(L"MappingMenu",   L"Menu");
00071     }
00072 
00073     this->fMapper->Initialize();
00074 
00075     fCfgWindow = fSkin->GetWindowByName(L"ConfigWindow");
00076     if (fCfgWindow)
00077     {
00078         fControllerMenu = (CATMenu*)fCfgWindow->FindControlAndVerify(L"ControllerMenu",L"Menu");
00079     }
00080 
00081     // Fill menus
00082     UpdateMappingMenu();
00083     UpdateControllerMenu();
00084 
00085 
00086     
00087     return result;
00088 }
00089 
00090 CATResult GASPilot::OnEnd(const CATResult& result)
00091 {
00092     fMapper->Uninitialize();
00093     return result;
00094 }
00095 
00096 CATResult GASPilot::OnEvent(const CATEvent& event, CATInt32& retVal)
00097 {
00098     if (event.fEventCode == CATEVENT_WINDOW_HIDDEN)
00099     {
00100         if ((event.fStringParam1.CompareNoCase(L"ProcessPick") == 0) ||
00101             (event.fStringParam1.CompareNoCase(L"ConfigWindow") == 0))
00102         {
00103             this->fWindow->SetEnabled(true);        
00104             ::SetForegroundWindow(fWindow->OSGetWnd());
00105         }
00106     }
00107     return CATApp::OnEvent(event, retVal);
00108 }
00109 
00110 CATResult GASPilot::MainLoop()
00111 {
00112     MSG msg;
00113     CATResult result = CAT_SUCCESS;
00114 
00115     while (::GetMessage(&msg,0,0,0))
00116     {
00117         ::TranslateMessage(&msg);
00118         ::DispatchMessage(&msg);
00119     }   
00120     return result;
00121 }
00122 
00123 
00124 // OnCommand() is called each time a command is received by the application.
00125 //
00126 // Most often, commands will come up from the Skin from controls. Each time
00127 // a button is clicked or a knob turned, for example.
00128 //
00129 // The commands are a class, primarily containing a command string that the
00130 // application should check to see if it supports. If so, the command should 
00131 // be performed.
00132 //
00133 // \param command - the command to execute
00134 // \param ctrl - the control that sent the command, or 0
00135 // \param wnd - the window of the control, or 0
00136 // \param skin - the skin the command came from, or 0
00137 void GASPilot::OnCommand(    CATCommand& command, 
00138                              CATControl* ctrl, 
00139                              CATWindow*  wnd, 
00140                              CATSkin*    skin)
00141 {
00142     CATString commandString = command.GetCmdString();
00143     CATResult result = CAT_SUCCESS;
00144 
00145     if (0 == commandString.Compare(L"GoWebsite"))
00146     {
00147         CATExecute(L"http://gameaccess.sourceforge.net",0);
00148     }
00149     else if (0 == commandString.Compare(L"Mapping"))
00150     {
00151         CATTRACE("Mapping Menu Cmd");
00152         SetActiveMapping(command.GetStringParam());
00153     }
00154     else if (0 == commandString.Compare(L"Controller"))
00155     {
00156         CATTRACE("Controller change cmd");
00157         if (this->fCfgWindow->FindControlAndVerify(L"ControllerSwitch",L"Switch")->GetValue() >= 0.5)
00158         {
00159             fMapper->StopMapping();
00160             fMapper->StartMapping(fControllerMenu->GetString(),this->fMappingMenu->GetString());
00161         }
00162     }
00163     else if (0 == commandString.Compare(L"App"))
00164     {
00165         CATTRACE("App Cmd");
00166         CATString execFile = ctrl->GetAttribute(L"AppPath");
00167         result = StartGame(execFile);
00168     }
00169     else if (0 == commandString.Compare(L"Pick"))
00170     {
00171         CATTRACE("Pick Cmd");
00172         std::vector<CATString> typeList;
00173         typeList.push_back(L"Executable Files|(*.exe)");
00174 
00175         CATString execFile = L"*.exe";
00176 
00177         if (CATSUCCEEDED(OpenFileDialog(L"Pick the game to execute",typeList,execFile,fWindow)))
00178         {
00179             result = StartGame(execFile);
00180         }
00181     }
00182     else if (0 == commandString.Compare(L"AppInject"))
00183     {
00184         CATString execFile = ctrl->GetAttribute(L"AppPath");
00185         CATString execName = execFile.GetFilenameExt();
00186         CATUInt32 pid = 0;
00187         if (CATSUCCEEDED(CATDLLInjector::GetProcessId(execName,pid)))
00188         {
00189             CATString dllPath = this->GetAppExePath().GetDriveDirectory() << L"GASPilotDLL.dll";
00190             CATDLLInjector::InjectIntoProcess(dllPath,pid);    
00191 
00192             CATString wndName = ctrl->GetAttribute(L"WndName");
00193             HWND wnd = ::FindWindow(0,wndName);
00194             if (wnd)
00195             {
00196                 ::ShowWindow(wnd,SW_RESTORE);
00197                 ::SetForegroundWindow(wnd);
00198             }
00199         }
00200 
00201         this->fWindow->SetEnabled(true);        
00202         this->fSkin->CloseWindow(L"ProcessPick");
00203     }
00204     else if (0 == commandString.Compare(L"Inject"))
00205     {
00206         this->fWindow->SetEnabled(false);        
00207         this->fSkin->OpenWindow(L"ProcessPick",fInjectWindow,fWindow,&fWindow->OSGetWndRect().Origin());        
00208         if (fInjectWindow)
00209         {
00210             /// Enumerate process windows
00211             fCurBtn = 0;
00212             EnumWindows(FillInjectWindow,(LPARAM)this);
00213         }
00214         else
00215         {
00216             this->fWindow->SetEnabled(true);
00217         }
00218     }
00219     else if (0 == commandString.Compare(L"Config"))
00220     {
00221         this->fWindow->SetEnabled(false);        
00222         this->fSkin->OpenWindow(L"ConfigWindow",fCfgWindow,fWindow,&fWindow->OSGetWndRect().Origin());        
00223         if (fCfgWindow)
00224         {
00225             // init?
00226         }
00227         else
00228         {
00229             this->fWindow->SetEnabled(true);
00230         }
00231     }
00232     else if (0 == commandString.Compare(L"CancelInject"))
00233     {
00234         this->fWindow->SetEnabled(true);        
00235         this->fSkin->CloseWindow(L"ProcessPick");
00236     }
00237     else if (0 == commandString.Compare(L"ExitCfg"))
00238     {
00239         this->fWindow->SetEnabled(true);        
00240         this->fSkin->CloseWindow(L"ConfigWindow");
00241     }
00242     else if (0 == commandString.Compare(L"Exit"))
00243     {
00244         this->fWindow->SetEnabled(true);        
00245         this->fSkin->CloseWindow(L"GASPilot");
00246     }    
00247     else if (0 == commandString.Compare(L"ControllerSwitch"))
00248     {
00249         if (command.GetValue() >= 0.5)
00250         {
00251             fMapper->StartMapping(fControllerMenu->GetString(),this->fMappingMenu->GetString());
00252             // Turn off mapping
00253         }
00254         else
00255         {
00256             fMapper->StopMapping();
00257             // Turn on mapping
00258         }
00259     }
00260     else
00261     {
00262         CATApp::OnCommand(command,ctrl,wnd,skin);
00263     }
00264 
00265     if (CATFAILED(result))
00266     {
00267         DisplayMessage( this->GetString(result),fWindow);
00268     }
00269 }
00270 
00271 BOOL CALLBACK GASPilot::FillInjectWindow( HWND hwnd,
00272                                           LPARAM lParam)
00273 {
00274     GASPilot* gp = (GASPilot*)lParam;
00275     return gp->OnInjectWindow(hwnd)?TRUE:FALSE;
00276 }
00277 
00278 bool GASPilot::OnInjectWindow(HWND hwnd)
00279 {
00280     if (!this->fInjectWindow)
00281         return false;
00282 
00283     if (fCurBtn >= 11)
00284         return false;
00285 
00286     DWORD procId = 0;
00287     GetWindowThreadProcessId(hwnd,&procId);
00288     CATString procPath;
00289     CATString wndName;
00290     
00291     // Get the name of the window
00292     ::GetWindowText(hwnd,wndName.GetUnicodeBuffer(100),99);
00293     wndName.ReleaseBuffer();
00294 
00295     DWORD style = ::GetWindowLong(hwnd,GWL_STYLE);
00296     DWORD styleEx = ::GetWindowLong(hwnd,GWL_EXSTYLE);
00297     if ( (!(style&WS_VISIBLE)) || (style & WS_CHILD) || 
00298          (style&WS_DISABLED) || (styleEx & WS_EX_TOOLWINDOW) || 
00299          (styleEx & WS_EX_CONTROLPARENT))
00300         return true;
00301 
00302     // Don't get empty ones.
00303     if (wndName.IsEmpty())
00304         return true;
00305 
00306     ::OutputDebugString(wndName);
00307     ::OutputDebugString(kCRLF);
00308 
00309     if (procId)
00310     {
00311         HANDLE process = ::OpenProcess(PROCESS_QUERY_INFORMATION |PROCESS_VM_READ,FALSE,procId);
00312         if (process != 0)
00313         {
00314             HMODULE hMod;
00315             DWORD cbNeeded;
00316 
00317             if ( EnumProcessModules( process, &hMod, sizeof(hMod), &cbNeeded) )
00318             {
00319                 ::GetModuleFileNameEx(process,hMod,procPath.GetUnicodeBuffer(1024),1023);
00320                 procPath.ReleaseBuffer();
00321             }
00322         }
00323     }
00324     
00325     if (procPath.IsEmpty())
00326         return true;
00327 
00328     if (procPath.GetFilenameNoExt().CompareNoCase(L"GASPilot") == 0)
00329         return true;
00330 
00331     // Got name and full path, now add to appbutton
00332     CATString btnName;
00333     btnName.Format(L"AppInject%d",fCurBtn+1);
00334     CATAppButton* curBtn = (CATAppButton*)fInjectWindow->FindControlAndVerify(btnName,L"AppButton");
00335     if (!curBtn)
00336         return false;
00337     ::OutputDebugString(procPath);
00338     curBtn->AddAttribute(L"AppPath",procPath);
00339     curBtn->AddAttribute(L"WndName",wndName);
00340     curBtn->SetEnabled(true);
00341     curBtn->ParseAttributes();
00342 
00343     fCurBtn++;
00344 
00345     return true;
00346 }
00347 
00348 void GASPilot::UpdateMappingMenu()
00349 {
00350     // Add in when the mapping object is done
00351     fMappingMenu->Clear();
00352     CATMENUITEM* newMenuItem = 0;        
00353     fMappingMenu->Insert(L"Speed Proto - PageUp/Down",0,newMenuItem,0);
00354     fMappingMenu->SetCurItem(newMenuItem);
00355 }
00356 
00357 void GASPilot::UpdateControllerMenu()
00358 {
00359     if (!fControllerMenu)
00360         return;
00361 
00362     CATString oldString = fControllerMenu->GetString();
00363 
00364     fMapper->StopMapping();
00365 
00366     fControllerMenu->Clear();
00367     std::vector<CATString> ctrlList;
00368     fMapper->GetControllerList(ctrlList);
00369     // Add in when the mapping object is done
00370     CATMENUITEM* newMenuItem = 0;        
00371     CATMENUITEM* firstMenuItem = 0;        
00372     CATMENUITEM* oldSel = 0;
00373     if (ctrlList.size() == 0)
00374     {
00375         fControllerMenu->Insert(L"None detected.",0,newMenuItem,0);
00376         firstMenuItem = newMenuItem;
00377         fControllerMenu->SetCurItem(newMenuItem);
00378     }
00379     else
00380     {
00381         for (CATUInt32 i = 0; i < ctrlList.size(); i++)
00382         {
00383             fControllerMenu->Insert( ctrlList[i],0,newMenuItem,0);
00384             if (oldString.Compare(ctrlList[i]) == 0)
00385                 oldSel = newMenuItem;
00386 
00387             if (!firstMenuItem)
00388                 firstMenuItem = newMenuItem;
00389         }
00390         if (oldSel)
00391             fControllerMenu->SetCurItem(oldSel);
00392         else
00393             fControllerMenu->SetCurItem(firstMenuItem);
00394 
00395         fMapper->StartMapping(fControllerMenu->GetString(),this->fMappingMenu->GetString());
00396     }        
00397 }
00398 
00399 CATResult GASPilot::SetActiveMapping(const CATString& mappingName)
00400 {
00401     CATString controlName;
00402  
00403     //fMapper.StartMapping();
00404     return CAT_SUCCESS;
00405 }
00406 
00407 CATResult GASPilot::StartGame(const CATWChar* executable)
00408 {
00409     CATResult result = CAT_SUCCESS;
00410 
00411     // Inject DLL and start
00412     CATString dllPath = this->GetAppExePath().GetDriveDirectory() << L"GASPilotDLL.dll";
00413     
00414     CATString appPath = executable;
00415     CATString appName = appPath.GetFilenameNoExt();
00416     
00417     if (0 == appName.CompareNoCase(L"steam"))
00418     {
00419         result = CATExecute(executable);
00420 
00421         // Check for an already running thread - if one's zombied, close it out.
00422         if (fSteamThread != 0)
00423         {
00424             if (WAIT_OBJECT_0 == WaitForSingleObject(fSteamThread,1000))
00425             {
00426                 CloseHandle(fSteamThread);
00427                 fSteamThread = 0;
00428             }
00429         }
00430 
00431         // If we don't have an active steam thread, start one.
00432         if (fSteamThread == 0)
00433         {
00434             unsigned int threadId = 0;
00435             fSteamThread = (HANDLE)_beginthreadex(0,0,SteamWatcher,this,0,&threadId);        
00436         }
00437     }
00438     else
00439     {
00440         result = CATDLLInjector::StartDLLWithProcess(dllPath,
00441                                                      executable,
00442                                                      executable);
00443     }
00444     return result;
00445 }
00446 void GASPilot::SteamWatch()
00447 {
00448     CATString dllPath = this->GetAppExePath().GetDriveDirectory() << L"GASPilotDLL.dll";
00449     CATUInt32 goupid  = 0;
00450     CATUInt32 gouLast = 0;
00451     CATUInt32 hl2pid  = 0;
00452     CATUInt32 hl2Last = 0;
00453 
00454     for (;;)
00455     {
00456         Sleep(100);
00457         
00458         // Check if steam's still running. If not, no need for the thread.
00459         // We don't inject into steam itself, as it appears to cause it to
00460         // refuse to login (protection? bug in my code? timing mismatch?)
00461         CATUInt32 steampid = 0;
00462         if (CATFAILED(CATDLLInjector::GetProcessId(L"steam.exe",steampid)))
00463         {
00464             break;
00465         }
00466 
00467         // Ok, now watch for HL2.exe
00468         if (CATSUCCEEDED(CATDLLInjector::GetProcessId(L"hl2.exe",hl2pid)))
00469         {
00470             if (hl2pid != hl2Last)
00471             {
00472                 CATDLLInjector::InjectIntoProcess(dllPath,hl2pid);    
00473                 hl2Last = hl2pid;
00474             }
00475         }
00476                                                    
00477         if (CATSUCCEEDED(CATDLLInjector::GetProcessId(L"gameoverlayui.exe",goupid)))
00478         {
00479             if (goupid != gouLast)
00480             {
00481                 CATDLLInjector::InjectIntoProcess(dllPath,gouLast);
00482             }
00483             gouLast = goupid;
00484         }
00485         
00486         // If we're hooked and running, relax a bit.
00487         if ((hl2Last != 0) && (hl2pid == hl2Last) && (gouLast != 0) && (goupid == gouLast))
00488         {
00489             Sleep(30000);
00490         }        
00491     }
00492 }
00493 
00494 
00495 unsigned int __stdcall GASPilot::SteamWatcher(void *param)
00496 {
00497     GASPilot* gp = (GASPilot*)param;
00498     gp->SteamWatch();
00499     return 0;
00500 }
00501 
00502 
00503 void GASPilot::OnHelp()
00504 {
00505     CATString helpPath = this->GetHelpDir();    
00506     helpPath << L"GASPilot.htm";
00507 
00508     CATResult result = CATExecute(helpPath);
00509     if (CATFAILED(result))
00510     {
00511         this->DisplayError(result,fWindow);        
00512     }
00513 }

Generated on Mon Feb 11 04:09:58 2008 for Game Accessibility Suite by doxygen 1.5.4