⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 giftlauncher.cpp

📁 Last change: 2008-02-03 This is the source code of KCeasy。
💻 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 + -