Initial commit: ROW Client source code

Game client codebase including:
- CharacterActionControl: Character and creature management
- GlobalScript: Network, items, skills, quests, utilities
- RYLClient: Main client application with GUI and event handlers
- Engine: 3D rendering engine (RYLGL)
- MemoryManager: Custom memory allocation
- Library: Third-party dependencies (DirectX, boost, etc.)
- Tools: Development utilities

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-29 16:24:34 +09:00
commit e067522598
5135 changed files with 1745744 additions and 0 deletions

View File

@@ -0,0 +1,750 @@
// PatchSFXDlg.cpp : implementation file
//
#include "stdafx.h"
#include "PatchSFX.h"
#include "PatchSFXDlg.h"
#include "ZipArchive.h"
#include "ZipStorage.h"
#include "atlenc.h"
#include <process.h>
#include ".\patchsfxdlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CPatchSFXDlg dialog
UINT IID_PROGRESS_EXTRACT_SFXFILES = 1;
UINT PROGRESS_UPDATE_TIME = 200;
void GetCurrentFolderName(CString& szCurrentFolderName)
{
TCHAR szFullPathName[MAX_PATH * 2];
GetModuleFileName(NULL, szFullPathName, MAX_PATH * 2 - 1);
szFullPathName[MAX_PATH * 2 - 1] = 0;
TCHAR szDrive[MAX_PATH];
TCHAR szDirectory[MAX_PATH];
_tsplitpath(szFullPathName, szDrive, szDirectory, 0, 0);
szCurrentFolderName.Format("%s%s", szDrive, szDirectory);
}
CPatchSFXDlg::CPatchSFXDlg(CWnd* pParent /*=NULL*/)
: CDialog(CPatchSFXDlg::IDD, pParent)
, m_szFileProgress(_T("0/0"))
, m_szPatchFileName(_T(""))
, m_szInstalledPathKey(_T(""))
, m_szRegKeyValue(_T(""))
, m_dwTotalFileSize(0LL)
, m_dwMinver(0L)
, m_dwMaxver(0L)
, m_nTotalFileNum(0)
, m_hExtractThread(0)
, m_nExtractThreadID(0)
, m_szCurrentExtract(_T(""))
{
m_SharedData.InitSharedData();
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CPatchSFXDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EXTRACT_POS, m_edExtractPos);
DDX_Control(pDX, IDC_EXTRACT_PROGRESS, m_prgExtract);
DDX_Control(pDX, IDC_BTN_PATCH_NOW, m_btnPatchNow);
DDX_Control(pDX, IDC_BTN_PATCH_LIST, m_btnPatchAdvanced);
DDX_Control(pDX, IDC_CONSOLE, m_edLog);
DDX_Text(pDX, IDC_PROGRESS_FILE, m_szFileProgress);
DDX_Text(pDX, IDC_CURRENT_EXTRACT, m_szCurrentExtract);
DDX_Control(pDX, IDC_BTN_EXTRACT_TO, m_btnExtractPos);
DDX_Control(pDX, IDC_PATCH_DONE, m_btnPatchDone);
DDX_Control(pDX, IDCANCEL, m_btnPatchCancel);
}
BEGIN_MESSAGE_MAP(CPatchSFXDlg, CDialog)
ON_WM_PAINT()
ON_WM_TIMER()
ON_WM_CLOSE()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BTN_EXTRACT_TO, OnBnClickedBtnExtractTo)
ON_BN_CLICKED(IDC_BTN_PATCH_NOW, OnBnClickedBtnPatchNow)
ON_BN_CLICKED(IDC_BTN_PATCH_LIST, OnBnClickedBtnPatchList)
ON_BN_CLICKED(IDC_PATCH_DONE, OnBnClickedPatchDone)
END_MESSAGE_MAP()
// CPatchSFXDlg message handlers
BOOL CPatchSFXDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
m_edLog.SetLimitText(UINT_MAX);
// <20>ڱ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>о, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>´<EFBFBD>.
CZipArchive zipFile;
CString szError;
TCHAR szBuff[MAX_PATH * 2];
if (!GetModuleFileName(NULL, szBuff, MAX_PATH * 2))
{
szError.Format(_T("Unable to find patch file : code(%d)"), GetLastError());
MessageBox(szError, _T("Patch error"), MB_OK | MB_ICONERROR);
PostQuitMessage(0);
}
else
{
szBuff[MAX_PATH * 2 - 1] = (TCHAR)0;
m_szPatchFileName.SetString(szBuff);
}
TRY
{
zipFile.Open(m_szPatchFileName, CZipArchive::zipOpenReadOnly);
CZipString szComment = zipFile.GetGlobalComment();
m_nTotalFileNum = zipFile.GetCount(true);
zipFile.Close();
int nDecodeBufferLen = Base64DecodeGetRequiredLength(szComment.GetLength());
int nDecodedDataLen = nDecodeBufferLen;
LPBYTE lpData = (LPBYTE) malloc(sizeof(BYTE) * nDecodeBufferLen);
if (!Base64Decode(szComment.GetString(), szComment.GetLength(), lpData, &nDecodedDataLen))
{
free(lpData);
szError.Format(_T("Unable to decode patch header : code(%d)"), GetLastError());
MessageBox(szError, _T("Patch error"), MB_OK | MB_ICONERROR);
PostQuitMessage(0);
}
else
{
CMemFile srcData(lpData, nDecodeBufferLen);
srcData.Read(&m_dwTotalFileSize, sizeof(m_dwTotalFileSize));
srcData.Read(&m_dwMinver, sizeof(m_dwMinver));
srcData.Read(&m_dwMaxver, sizeof(m_dwMaxver));
int nInstalledPathLen = 0;
int nValueNameLen = 0;
TCHAR szInstalledPathKey[MAX_PATH];
TCHAR szRegKeyValue[MAX_PATH];
srcData.Read(&nInstalledPathLen, sizeof(nInstalledPathLen));
srcData.Read(&nValueNameLen, sizeof(nValueNameLen));
srcData.Read(szInstalledPathKey, sizeof(TCHAR) * nInstalledPathLen);
m_szInstalledPathKey.SetString(szInstalledPathKey, nInstalledPathLen);
srcData.Read(szRegKeyValue, sizeof(TCHAR) * nValueNameLen);
m_szRegKeyValue.SetString(szRegKeyValue, nValueNameLen);
}
}
CATCH_ALL(e)
{
DWORD dwError = GetLastError();
if (e->IsKindOf(RUNTIME_CLASS(CZipException)))
{
szError.Format(_T("Read Patch Header From Archive Error : code(%d)"), dwError);
}
else
{
szError.Format(_T("Invalid Patch Header : code(%d)"), dwError);
}
MessageBox(szError, _T("Patch error"), MB_OK | MB_ICONERROR);
PostQuitMessage(0);
}
END_CATCH_ALL;
CRegKey regKey;
TCHAR szInstalledBuffer[MAX_PATH * 2];
ULONG nBufferSize = MAX_PATH * 2 - 1;
if (ERROR_SUCCESS == regKey.Open(HKEY_LOCAL_MACHINE, m_szInstalledPathKey, KEY_READ) &&
ERROR_SUCCESS == regKey.QueryStringValue(m_szRegKeyValue, szInstalledBuffer, &nBufferSize))
{
szInstalledBuffer[MAX_PATH * 2 - 1] = (TCHAR)0;
CString szInstalledPath(szInstalledBuffer);
szInstalledPath.Trim();
int nLength = szInstalledPath.GetLength();
if (1 < nLength && szInstalledPath.GetString()[nLength - 1] != _T('\\'))
{
szInstalledPath.Append(_T("\\"));
}
m_edExtractPos.SetWindowText(szInstalledPath);
UpdateData(FALSE);
}
CString szWindowTitle;
/*
if (m_dwMaxver < 1000)
{
szWindowTitle.Format(_T("RYL Part1 Patch (version %d to %d)"),
m_dwMinver + 100, m_dwMaxver + 100);
}
else
{
szWindowTitle.Format(_T("RYL Part2 Patch (version %d to %d)"),
m_dwMinver, m_dwMaxver);
}
*/
szWindowTitle.Format(_T("Return of Warrior Patch (version %d to %d)"),
m_dwMinver, m_dwMaxver);
SetWindowText(szWindowTitle);
return TRUE; // return TRUE unless you set the focus to a control
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CPatchSFXDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND,
reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CPatchSFXDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CPatchSFXDlg::OnBnClickedBtnExtractTo()
{
CString szFolderName;
BROWSEINFO brInfo;
memset(&brInfo, 0, sizeof(BROWSEINFO));
TCHAR szTemp[MAX_PATH * 2];
brInfo.hwndOwner = GetSafeHwnd();
brInfo.pidlRoot = NULL;
brInfo.pszDisplayName = szTemp;
brInfo.lpszTitle = _T("Select patch extract folder");
brInfo.ulFlags = BIF_USENEWUI | BIF_RETURNONLYFSDIRS;
LPITEMIDLIST lpItemIDList = SHBrowseForFolder(&brInfo);
if (NULL != lpItemIDList && SHGetPathFromIDList(lpItemIDList, szTemp))
{
szTemp[MAX_PATH * 2 - 1] = (TCHAR)0;
szFolderName.SetString(szTemp);
szFolderName.Trim();
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>̹Ƿ<CCB9>, <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ڰ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ٿ<EFBFBD> <20>ش<EFBFBD>.
int nLength = szFolderName.GetLength();
if (1 < nLength && _T('\\') != szFolderName.GetString()[nLength - 1])
{
szFolderName.Append(_T("\\"));
}
}
if (!szFolderName.IsEmpty())
{
m_edExtractPos.SetWindowText(szFolderName);
m_btnPatchDone.ShowWindow(SW_HIDE);
m_btnPatchNow.ShowWindow(SW_SHOW);
m_btnPatchCancel.ShowWindow(SW_SHOW);
UpdateData(FALSE);
}
}
struct ExtractWorkerData
{
CPatchSFXDlg* m_lpDlg;
CString m_szExtractPos;
DWORD m_dwMinver;
DWORD m_dwMaxver;
};
unsigned __stdcall CPatchSFXDlg::ExtractWorker(void *pArg)
{
ExtractWorkerData* lpWorkerData =
reinterpret_cast<ExtractWorkerData*>(pArg);
CPatchSFXDlg* lpDlg = lpWorkerData->m_lpDlg;
SharedData sharedData;
TCHAR szFileName[MAX_PATH * 2];
GetModuleFileName(NULL, szFileName, MAX_PATH * 2);
szFileName[MAX_PATH * 2 - 1] = 0;
CZipArchive zipFile;
CZipFileHeader fhInfo;
CString szError;
const int MAX_ERROR_LEN = 256;
TCHAR szErrorMsg[MAX_ERROR_LEN];
bool bFailedExtract = false;
TRY
{
zipFile.Open(szFileName, CZipArchive::zipOpenReadOnly);
int nTotalFileNum = zipFile.GetCount();
zipFile.SetRootPath(lpWorkerData->m_szExtractPos);
for (; !sharedData.m_bStopWorkerThread && sharedData.m_nCurrentFiles < nTotalFileNum;
++sharedData.m_nCurrentFiles)
{
if (!zipFile.GetFileInfo(fhInfo, sharedData.m_nCurrentFiles))
{
szError.SetString(CTime::GetCurrentTime().Format(_T("[%H:%M:%S]")));
szError.AppendFormat(_T("Get fileinfo failed : index(%d)"),
sharedData.m_nCurrentFiles);
sharedData.m_ProgressList.AddTail(szError);
bFailedExtract = true;
}
else
{
sharedData.m_szCurrentExtract.SetString(
zipFile.PredictExtractedFileName(fhInfo.GetFileName(),
lpWorkerData->m_szExtractPos, true));
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ӽ<EFBFBD><D3BC><EFBFBD> Normal<61><6C>
SetFileAttributes(sharedData.m_szCurrentExtract,
FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_ARCHIVE);
lpDlg->UpdateProgress(sharedData);
if (!zipFile.ExtractFile(sharedData.m_nCurrentFiles, lpWorkerData->m_szExtractPos))
{
szError.SetString(CTime::GetCurrentTime().Format(_T("[%H:%M:%S]")));
szError.AppendFormat(_T("Extract file failed! : %s%s"),
lpWorkerData->m_szExtractPos, fhInfo.GetFileName());
sharedData.m_ProgressList.AddTail(szError);
bFailedExtract = true;
}
sharedData.m_nCurrentDataSize += fhInfo.m_uUncomprSize;
}
lpDlg->UpdateProgress(sharedData);
}
szError.SetString(CTime::GetCurrentTime().Format(_T("[%H:%M:%S]")));
if (sharedData.m_bStopWorkerThread)
{
szError.AppendFormat(_T("Canceled extract patch."));
}
else if (bFailedExtract)
{
szError.AppendFormat(_T("Failed to extract patch."));
}
else
{
CString szVersionInfoFileName;
CString szCurrentVersion;
szVersionInfoFileName.Format(_T("%sVersionInfo.dat"),
lpWorkerData->m_szExtractPos);
szCurrentVersion.Format(_T("%d"), lpWorkerData->m_dwMaxver);
CStdioFile file;
if (!file.Open(szVersionInfoFileName,
CFile::modeCreate | CFile::modeWrite | CFile::typeText))
{
szError.AppendFormat(_T("Failed to write version info!"));
}
else
{
file.WriteString(szCurrentVersion);
szError.AppendFormat(_T("Patch Complete! : %s"), lpWorkerData->m_szExtractPos);
}
}
sharedData.m_ProgressList.AddTail(szError);
zipFile.Close();
}
CATCH_ALL(e)
{
e->GetErrorMessage(szErrorMsg, MAX_ERROR_LEN - 1);
szErrorMsg[MAX_ERROR_LEN - 1] = 0;
if (e->IsKindOf(RUNTIME_CLASS(CZipException)))
{
szError.Format(_T("Extract failed : zipArchive error! (%s)"), szErrorMsg);
}
else
{
szError.Format(_T("Extract failed : unknown error! (%s)"), szErrorMsg);
}
sharedData.m_ProgressList.AddTail(szError);
}
END_CATCH_ALL;
delete lpWorkerData;
lpDlg->UpdateProgress(sharedData);
return 0;
}
void CPatchSFXDlg::UpdateProgress(SharedData& sharedData)
{
m_csProgress.Lock();
sharedData.m_bStopWorkerThread = m_SharedData.m_bStopWorkerThread;
m_SharedData.m_nCurrentFiles = sharedData.m_nCurrentFiles;
m_SharedData.m_nCurrentDataSize = sharedData.m_nCurrentDataSize;
m_SharedData.m_szCurrentExtract = sharedData.m_szCurrentExtract;
m_SharedData.m_ProgressList.AddTail(&sharedData.m_ProgressList);
m_csProgress.Unlock();
sharedData.m_ProgressList.RemoveAll();
}
afx_msg void CPatchSFXDlg::OnTimer(UINT_PTR nIDEvent)
{
if (nIDEvent == IID_PROGRESS_EXTRACT_SFXFILES)
{
// <20><><EFBFBD><EFBFBD><EFBFBD>͸<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><20><><EFBFBD><EFBFBD><EFBFBD>Ǿ<EFBFBD><C7BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
int nLower = 0;
int nUpper = 0;
m_prgExtract.GetRange(nLower, nUpper);
int nCurrentPos = m_prgExtract.GetPos();
// <20><><EFBFBD><EFBFBD> <20>Ǵ<EFBFBD>
m_csProgress.Lock();
if (nUpper != static_cast<int>(m_dwTotalFileSize))
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ٲ<EFBFBD><D9B2><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
m_prgExtract.SetRange32(0, static_cast<int>(m_dwTotalFileSize));
}
if (nCurrentPos != m_SharedData.m_nCurrentDataSize)
{
// <20><><EFBFBD><EFBFBD> <20><>ġ <20><><EFBFBD><EFBFBD>
m_prgExtract.SetPos(m_SharedData.m_nCurrentDataSize);
}
m_szCurrentExtract.SetString(m_SharedData.m_szCurrentExtract);
m_szFileProgress.Format(_T("%d/%d"),
m_SharedData.m_nCurrentFiles, m_nTotalFileNum);
// <20>α<EFBFBD> <20>޽<EFBFBD><DEBD><EFBFBD><EFBFBD><EFBFBD> ȭ<><20>Ѹ<EFBFBD><D1B8><EFBFBD>.
POSITION pos = m_SharedData.m_ProgressList.GetHeadPosition();
while(0 != pos) { m_edLog.AddLine(m_SharedData.m_ProgressList.GetNext(pos)); }
m_SharedData.m_ProgressList.RemoveAll();
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
m_csProgress.Unlock();
UpdateData(FALSE);
if (WAIT_OBJECT_0 == WaitForSingleObject(m_hExtractThread, 0))
{
StopWorker();
if (!m_PatchFolderList.IsEmpty())
{
m_edExtractPos.SetWindowText(m_PatchFolderList.RemoveHead());
UpdateData(FALSE);
// <20><>ġ<EFBFBD><C4A1><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20><>ġ<EFBFBD><C4A1> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><> <20><>ġ<EFBFBD><C4A1> <20>Ѵ<EFBFBD>..
PostMessage(WM_COMMAND, MAKEWPARAM(IDC_BTN_PATCH_NOW, BN_CLICKED));
}
else
{
m_btnPatchDone.ShowWindow(SW_SHOW);
m_btnPatchNow.ShowWindow(SW_HIDE);
m_btnPatchCancel.ShowWindow(SW_HIDE);
}
}
}
}
bool CPatchSFXDlg::CheckExtractPosVersion()
{
// <20><><EFBFBD><EFBFBD> <20><>ġ<EFBFBD><C4A1> VersionInfo.dat<61><74><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ֳ<EFBFBD> <20><><EFBFBD><20>ڿ<EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ּҹ<D6BC><D2B9><EFBFBD> / <20>ִ<EFBFBD><D6B4><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ɴ<EFBFBD>.
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD≯<EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ġ<EFBFBD><C4A1> <20><> <20><><EFBFBD><EFBFBD><EEBABB>.
UpdateData(TRUE);
CString szError;
CString szVersion;
CString szExtractPos;
CString szVersionInfoFileName;
m_edExtractPos.GetWindowText(szExtractPos);
szVersionInfoFileName.Format(_T("%sVersionInfo.dat"), szExtractPos);
CStdioFile file;
if (file.Open(szVersionInfoFileName, CFile::modeRead | CFile::typeText))
{
file.ReadString(szVersion);
DWORD dwVersion = _ttol(szVersion);
if (dwVersion < m_dwMinver)
{
MessageBox(_T("Current version is too low, try other patch first"),
_T("Patch error"), MB_OK | MB_ICONERROR);
return false;
}
else if (m_dwMaxver < dwVersion &&
IDNO == MessageBox(_T("Current version is higher than this patch version. Overwrite it?"),
_T("Question"), MB_YESNO | MB_ICONEXCLAMATION))
{
return false;
}
}
return true;
}
void CPatchSFXDlg::OnBnClickedBtnPatchNow()
{
// TODO: <20><><EFBFBD><20><>Ʈ<EFBFBD><C6AE> <20>˸<EFBFBD> ó<><C3B3><EFBFBD><EFBFBD> <20>ڵ带 <20>߰<EFBFBD><DFB0>մϴ<D5B4>.
UpdateData(TRUE);
CString szError;
CString szPatchFolder;
bool bFailedAndCleanup = true;
ExtractWorkerData* lpWorkerData = new ExtractWorkerData;
if (0 != lpWorkerData)
{
m_edExtractPos.GetWindowText(szPatchFolder);
lpWorkerData->m_lpDlg = this;
lpWorkerData->m_dwMinver = m_dwMinver;
lpWorkerData->m_dwMaxver = m_dwMaxver;
lpWorkerData->m_szExtractPos.SetString(szPatchFolder);
if (0 != m_hExtractThread)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><20>̹<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. <20><><EFBFBD><EFBFBD> <20><>ư<EFBFBD><C6B0> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>þ<EFBFBD><C3BE>ݽô<DDBD>.
}
else if (lpWorkerData->m_szExtractPos.IsEmpty())
{
MessageBox(_T("Invalid Extract Position. Please set extract position"),
_T("Patch Error"), MB_OK | MB_ICONERROR);
PostMessage(WM_COMMAND, MAKEWPARAM(IDC_BTN_EXTRACT_TO, BN_CLICKED));
}
else if (CheckExtractPosVersion())
{
m_hExtractThread = reinterpret_cast<HANDLE>(
_beginthreadex(0, 0, ExtractWorker, lpWorkerData, 0, &m_nExtractThreadID));
if (0 == m_hExtractThread)
{
szError.Format(_T("Create extract thread failed : code(%d)"), GetLastError());
MessageBox(szError, _T("Patch Error"), MB_OK | MB_ICONERROR);
}
else
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
bFailedAndCleanup = false;
// ȭ<><C8AD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD> Ÿ<≯Ӹ<CCB8> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
SetTimer(IID_PROGRESS_EXTRACT_SFXFILES, PROGRESS_UPDATE_TIME, NULL);
// <20><>ġ <20><>ư<EFBFBD><C6B0> <20><> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ѵ<EFBFBD>.
m_btnPatchNow.EnableWindow(FALSE);
m_btnPatchAdvanced.EnableWindow(FALSE);
m_btnExtractPos.EnableWindow(FALSE);
}
}
}
if (bFailedAndCleanup)
{
delete lpWorkerData;
}
}
void CPatchSFXDlg::StopWorker()
{
if (0 != m_hExtractThread)
{
m_csProgress.Lock();
m_SharedData.m_bStopWorkerThread = TRUE;
m_csProgress.Unlock();
WaitForSingleObject(m_hExtractThread, INFINITE);
KillTimer(IID_PROGRESS_EXTRACT_SFXFILES);
// <20><><EFBFBD><EFBFBD><EFBFBD><20><><EFBFBD><EFBFBD><EFBFBD>Ǿ<EFBFBD><C7BE><EFBFBD>.
CloseHandle(m_hExtractThread);
m_hExtractThread = 0;
m_nExtractThreadID = 0;
m_SharedData.InitSharedData();
m_btnPatchNow.EnableWindow(TRUE);
m_btnPatchAdvanced.EnableWindow(TRUE);
m_btnExtractPos.EnableWindow(TRUE);
}
}
void CPatchSFXDlg::OnClose()
{
// TODO: <20><><EFBFBD><20>޽<EFBFBD><DEBD><EFBFBD> ó<><C3B3><EFBFBD><EFBFBD> <20>ڵ带 <20>߰<EFBFBD> <20><>/<2F>Ǵ<EFBFBD> <20><EFBFBD><E2BABB><EFBFBD><EFBFBD> ȣ<><C8A3><EFBFBD>մϴ<D5B4>.
m_PatchFolderList.RemoveAll();
StopWorker();
CDialog::OnClose();
}
void CPatchSFXDlg::OnBnClickedBtnPatchList()
{
// TODO: <20><><EFBFBD><20><>Ʈ<EFBFBD><C6AE> <20>˸<EFBFBD> ó<><C3B3><EFBFBD><EFBFBD> <20>ڵ带 <20>߰<EFBFBD><DFB0>մϴ<D5B4>.
// <20><>ġ<EFBFBD><C4A1><EFBFBD><EFBFBD>Ʈ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ã<>Ƽ<EFBFBD> <20>д´<D0B4>.
// <20><><EFBFBD>Ͽ<EFBFBD><CFBF><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20>д´<D0B4>.
// ù<><C3B9>° <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ڽ<EFBFBD><DABD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
// <20><>ġ <20><>ư<EFBFBD><C6B0> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ѵ<EFBFBD>.
CString szLog;
CString szPatchFolder;
CString szFolderListFile;
GetCurrentFolderName(szFolderListFile);
szFolderListFile.AppendFormat(_T("PatchFolders.ini"));
CStdioFile folderList;
if (folderList.Open(szFolderListFile,
CFile::modeCreate | CFile::modeNoTruncate | CFile::modeRead | CFile::shareDenyNone | CFile::typeText))
{
while(folderList.ReadString(szPatchFolder))
{
szPatchFolder.Trim();
szPatchFolder.Replace(_T('/'), _T('\\'));
int nLength = szPatchFolder.GetLength();
if (1 < nLength && szPatchFolder.GetString()[nLength - 1] != _T('\\'))
{
szPatchFolder.Append(_T("\\"));
}
if (INVALID_FILE_ATTRIBUTES != GetFileAttributes(szPatchFolder))
{
m_PatchFolderList.AddTail(szPatchFolder);
}
else
{
szLog.SetString(CTime::GetCurrentTime().Format(_T("[%H:%M:%S]")));
szLog.AppendFormat(_T("Invalid folder %s : Please write existing folder"),
szPatchFolder);
m_edLog.AddLine(szLog);
}
}
if (!m_PatchFolderList.IsEmpty())
{
POSITION pos = m_PatchFolderList.GetHeadPosition();
while (0 != pos)
{
CString& szReadyPatchFolder = m_PatchFolderList.GetNext(pos);
szLog.SetString(CTime::GetCurrentTime().Format(_T("[%H:%M:%S]")));
szLog.AppendFormat(_T("Ready to patch %s folder now!"), szReadyPatchFolder);
m_edLog.AddLine(szLog);
}
m_btnPatchDone.ShowWindow(SW_HIDE);
m_btnPatchNow.ShowWindow(SW_SHOW);
m_btnPatchCancel.ShowWindow(SW_SHOW);
m_edExtractPos.SetWindowText(m_PatchFolderList.RemoveHead());
UpdateData(FALSE);
// <20><>ġ<EFBFBD><C4A1><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20><>ġ<EFBFBD><C4A1> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><> <20><>ġ<EFBFBD><C4A1> <20>Ѵ<EFBFBD>..
PostMessage(WM_COMMAND, MAKEWPARAM(IDC_BTN_PATCH_NOW, BN_CLICKED));
}
else
{
szLog.SetString(CTime::GetCurrentTime().Format(_T("[%H:%M:%S]")));
szLog.AppendFormat(_T("There is no folder list in %s file\nPlease edit contents"),
szFolderListFile);
MessageBox(szLog, "Patch Error", MB_OK | MB_ICONEXCLAMATION);
}
}
else
{
szLog.SetString(CTime::GetCurrentTime().Format(_T("[%H:%M:%S]")));
szLog.AppendFormat(_T("Open %s file failed\nPlease edit contents"), szFolderListFile);
MessageBox(szLog, "Patch Error", MB_OK | MB_ICONEXCLAMATION);
}
}
void CPatchSFXDlg::OnBnClickedPatchDone()
{
// TODO: <20><><EFBFBD><20><>Ʈ<EFBFBD><C6AE> <20>˸<EFBFBD> ó<><C3B3><EFBFBD><EFBFBD> <20>ڵ带 <20>߰<EFBFBD><DFB0>մϴ<D5B4>.
PostQuitMessage(0);
}