Files
Client/Tools/PatchSFX/PatchSFXDlg.cpp
LGram16 e067522598 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>
2025-11-29 16:24:34 +09:00

751 lines
22 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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);
}