📄 giftlauncher.cpp
字号:
/*
This file is part of KCeasy (http://www.kceasy.com)
Copyright (C) 2002-2004 Markus Kern <mkern@kceasy.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
//---------------------------------------------------------------------------
#pragma hdrstop
#include "GiftLauncher.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
namespace KCeasyEngine {
const char* GIFT_GLOBAL_REG_KEY = "HKLM\\Software\\giFT\\giFT\\instpath";
const char* GIFT_GLOBAL_CONF_PATH = "\\giftd.conf";
const char* GIFT_GLOBAL_EXE_PATH = "\\giFT.exe";
// relative to kceasy.exe
const char* GIFT_DIR = "\\giFT";
// relative to GIFT_DIR
const char* GIFT_EXE_PATH = "\\giFTl.exe";
const char* GIFT_DLL_PATH = "\\giFTd.dll";
const char* GIFT_HOME_DIR = "\\conf";
const char* GIFT_LOCAL_DIR = "\\conf";
const char* GIFT_DATA_DIR = "\\data";
const char* GIFT_PLUGIN_DIR = "\\plugins";
const char* GIFT_CONF_PATH = "\\conf\\giftd.conf";
// global thread function
DWORD WINAPI ThreadFunc(void* data)
{
((TGiftLauncher*)data)->DllThreadFunc();
return 0;
}
// class TFileConfig
// public
TGiftLauncher::TGiftLauncher()
: ProcessHandle(NULL),
ThreadHandle(NULL),
GiftStdReadPipe(NULL),
GiftStdWritePipe(NULL),
DllInst(NULL),
GiftConf(NULL),
GlobalGift(false)
{
}
TGiftLauncher::~TGiftLauncher()
{
#if 0
// take giFT with us if running
if(IsRunning())
Kill();
#endif
delete GiftConf;
}
bool TGiftLauncher::InitGlobal()
{
char* Path;
if(IsRunning())
return false;
GiftPath = "";
delete GiftConf;
GiftConf = NULL;
GlobalGift = false;
if((Path = ReadRegKey(GIFT_GLOBAL_REG_KEY)) == NULL)
return false;
DWORD Attributes = GetFileAttributes(Path);
if(Attributes == 0xFFFFFFFF || !(Attributes & FILE_ATTRIBUTE_DIRECTORY)) {
free (Path);
return false;
}
GiftConf = new TFileConfig(GetGiftPath() + GIFT_GLOBAL_CONF_PATH);
if(!GiftConf->Load(true)) {
delete GiftConf;
GiftConf = NULL;
free (Path);
return false;
}
GiftPath = Path;
GlobalGift = true;
return true;
}
bool TGiftLauncher::Init()
{
char ModulePath[MAX_PATH];
if(IsRunning())
return false;
GiftPath = "";
delete GiftConf;
GiftConf = NULL;
GlobalGift = false;
if(!GetModuleFileName(NULL, ModulePath, MAX_PATH))
return false;
GiftPath = ModulePath;
GiftPath.erase(GiftPath.rfind('\\'));
GiftPath += GIFT_DIR;
DWORD Attributes = GetFileAttributes(GiftPath.c_str());
if(Attributes == 0xFFFFFFFF || !(Attributes & FILE_ATTRIBUTE_DIRECTORY)) {
GiftPath = "";
return false;
}
GiftConf = new TFileConfig(GetGiftPath() + GIFT_CONF_PATH);
if(!GiftConf->Load(true)) {
delete GiftConf;
GiftConf = NULL;
GiftPath = "";
return false;
}
return true;
}
const string& TGiftLauncher::GetGiftPath()
{
return GiftPath;
}
string TGiftLauncher::GetPluginPath()
{
return GiftPath + GIFT_PLUGIN_DIR;
}
string TGiftLauncher::GetConfPath()
{
return GiftPath + GIFT_LOCAL_DIR;
}
bool TGiftLauncher::Launch()
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
string CmdLine;
DWORD FileAttr;
if(IsRunning())
return false;
CloseHandle(GiftStdReadPipe); GiftStdReadPipe = NULL;
CloseHandle(GiftStdWritePipe); GiftStdWritePipe = NULL;
ProcessHandle = NULL;
ThreadHandle = NULL;
DllInst = NULL;
if(IsUsingGlobal()) {
CmdLine = "\"";
CmdLine += GiftPath;
CmdLine += GIFT_GLOBAL_EXE_PATH;
CmdLine += "\" -d";
} else {
// quote exe path so CreateProcess doesn't do crazy things like running
// C:\program.exe
CmdLine = string ("\"") + GiftPath + GIFT_EXE_PATH + "\"";
CmdLine += " -d -v";
CmdLine += string(" \"--home-dir=") + GiftPath + GIFT_HOME_DIR + "\"";
CmdLine += string(" \"--local-dir=") + GiftPath + GIFT_LOCAL_DIR + "\"";
CmdLine += string(" \"--data-dir=") + GiftPath + GIFT_DATA_DIR + "\"";
CmdLine += string(" \"--plugin-dir=") + GiftPath + GIFT_PLUGIN_DIR + "\"";
}
memset(&si,0,sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_FORCEOFFFEEDBACK; // no hourglass cursor
// create pipe for receveiving giFT's stdout an stderr
SECURITY_ATTRIBUTES sa;
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
// Need to create pipe with a large buffer so giFT does not block on stderr
// logging on shutdown when we are no longer reading from the pipe
if(CreatePipe(&GiftStdReadPipe,&GiftStdWritePipe,&sa,64*1024)) {
si.dwFlags |= STARTF_USESTDHANDLES;
si.hStdOutput = GiftStdWritePipe;
si.hStdError = GiftStdWritePipe;
si.hStdInput = NULL;
}
// Launch giFT
if(!CreateProcess(NULL,(char*)CmdLine.c_str(),NULL,NULL,TRUE,CREATE_DEFAULT_ERROR_MODE,NULL,GiftPath.c_str(),&si,&pi))
return false;
ProcessHandle = pi.hProcess;
ThreadHandle = pi.hThread;
WaitForInputIdle(pi.hProcess,500);
return true;
}
bool TGiftLauncher::LaunchDll()
{
DWORD ThreadId;
if(IsRunning())
return false;
ProcessHandle = NULL;
ThreadHandle = NULL;
DllInst = NULL;
DllInst = LoadLibraryEx((GiftPath + GIFT_DLL_PATH).c_str(),0,LOAD_WITH_ALTERED_SEARCH_PATH);
if(DllInst == NULL)
return false;
if(GetProcAddress(DllInst, "gift_main") == NULL) {
FreeLibrary(DllInst);
DllInst = NULL;
return false;
}
ThreadHandle = CreateThread(NULL,0,ThreadFunc,(void*)this,0,&ThreadId);
if(ThreadHandle == NULL) {
FreeLibrary(DllInst);
DllInst = NULL;
return false;
}
return true;
}
bool TGiftLauncher::Kill()
{
if(!IsRunning())
return false;
if(IsUsingDll()) {
TerminateThread(ThreadHandle,0);
FreeLibrary(DllInst);
} else {
TerminateProcess(ProcessHandle,0);
}
CloseHandle(GiftStdReadPipe);
CloseHandle(GiftStdWritePipe);
ProcessHandle = NULL;
ThreadHandle = NULL;
DllInst = NULL;
return true;
}
bool TGiftLauncher::IsRunning()
{
if(ThreadHandle == NULL)
return false;
if(WaitForSingleObject(ThreadHandle, 0) == WAIT_OBJECT_0)
return false;
return true;
}
// return true if terminated, false if timeout
bool TGiftLauncher::WaitForTermination(int msecs)
{
if(ThreadHandle == NULL)
return true;
if(IsUsingDll()) {
if(WaitForSingleObject(ThreadHandle,msecs) == WAIT_TIMEOUT)
return false;
} else {
if(WaitForSingleObject(ProcessHandle,msecs) == WAIT_TIMEOUT)
return false;
}
return true;
}
void TGiftLauncher::CloseStdoutHandle()
{
CloseHandle(GiftStdReadPipe);
CloseHandle(GiftStdWritePipe);
}
// private
void TGiftLauncher::DllThreadFunc()
{
#if 0
int (*gift_main)(int argc, char **argv);
char argv[6][MAX_PATH+32];
HINSTANCE DllInstance = DllInst;
gift_main = (int(*)(int, char**))GetProcAddress(DllInstance, "gift_main");
if(gift_main == NULL) {
FreeLibraryAndExitThread(DllInst, 0);
return;
}
wsprintf(argv[0], "%s%s", GiftPath.c_str(), GIFT_DLL_PATH);
wsprintf(argv[1], "-d");
wsprintf(argv[2], "--home-dir=%s%s", GiftPath.c_str(), GIFT_HOME_DIR);
wsprintf(argv[3], "--local-dir=%s%s", GiftPath.c_str(), GIFT_LOCAL_DIR);
wsprintf(argv[4], "--data-dir=%s%s", GiftPath.c_str(), GIFT_DATA_DIR);
wsprintf(argv[5], "--plugin-dir=%s%s", GiftPath.c_str(), GIFT_PLUGIN_DIR);
try {
if(gift_main(6, (char**)argv) != 0) {
::MessageBox(0,"GiftLauncher", "gift_main() failed", MB_OK);
} else {
::MessageBox(0,"GiftLauncher", "gift_main() succeeded", MB_OK);
}
}
catch(const EAssertionFailed& e) {
::MessageBox(0,"GiftLauncher - assertion failed", e.Message.c_str(),MB_OK);
}
catch(const EAccessViolation& e) {
::MessageBox(0,"GiftLauncher - access violation", e.Message.c_str(),MB_OK);
}
catch(...) {
::MessageBox(0,"GiftLauncher - unknown exception", "unknown exception triggered",MB_OK);
}
ThreadHandle = NULL;
DllInst = NULL;
ProcessHandle = NULL;
FreeLibraryAndExitThread(DllInstance, 0);
return;
#endif
}
} // namespace KCeasyEngine
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -