// PatchSFXDlg.cpp : implementation file // #include "stdafx.h" #include "PatchSFX.h" #include "PatchSFXDlg.h" #include "ZipArchive.h" #include "ZipStorage.h" #include "atlenc.h" #include #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); // ÀÚ±â ÆÄÀÏÀ» Àо, Á¤º¸¸¦ ¾ò¾î¿Â´Ù. 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(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(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(); // °æ·Î ¼³Á¤À̹ǷÎ, ¸Ç ¸¶Áö¸· ±ÛÀÚ°¡ ¿ª½½·¡½¬·Î ³¡³ªÁö ¾ÊÀ» °æ¿ì, ¿ª½½·¡½¬¸¦ ºÙ¿© ÁØ´Ù. 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(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)); // ÆÄÀÏÀÌ ÀÖÀ¸¸é ¼Ó¼ºÀ» Normal·Î 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) { // µ¥ÀÌÅ͸¦ °»½ÅÇϰí, ½º·¹µå°¡ Á¾·áµÇ¾ú´ÂÁö¸¦ °ËÃâÇÑ´Ù. int nLower = 0; int nUpper = 0; m_prgExtract.GetRange(nLower, nUpper); int nCurrentPos = m_prgExtract.GetPos(); // ¶ôÀ» °Ç´Ù m_csProgress.Lock(); if (nUpper != static_cast(m_dwTotalFileSize)) { // ¹üÀ§°¡ ¹Ù²î¸é ¹üÀ§ ¼³Á¤ m_prgExtract.SetRange32(0, static_cast(m_dwTotalFileSize)); } if (nCurrentPos != m_SharedData.m_nCurrentDataSize) { // ÇöÀç À§Ä¡ ¼³Á¤ 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); // ·Î±× ¸Þ½ÃÁö¸¦ È­¸é¿¡ »Ñ¸°´Ù. POSITION pos = m_SharedData.m_ProgressList.GetHeadPosition(); while(0 != pos) { m_edLog.AddLine(m_SharedData.m_ProgressList.GetNext(pos)); } m_SharedData.m_ProgressList.RemoveAll(); // ¶ôÀ» ÇØÁ¦ÇÑ´Ù. 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); // ÆÐÄ¡¸®½ºÆ®¿¡ ÆÐÄ¡°¡ ³²¾Æ ÀÖÀ¸¸é, ¶Ç ÆÐÄ¡¸¦ ÇÑ´Ù.. 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() { // ÆÄÀÏ À§Ä¡¿¡ VersionInfo.datÆÄÀÏÀÌ ÀÖ³ª »ìÆìº» µÚ¿¡, ÀÖÀ¸¸é ÃÖ¼Ò¹öÀü / ÃÖ´ë¹öÀü »çÀÌÀÇ °ªÀÎÁö »ìÇÉ´Ù. // ¸¸ÀÏ ÆÄÀÏÀÌ Á¸ÀçÇϰí, ¹öÀüÀÌ ¹üÀ§ ¹ÛÀÇ °ªÀ̸é, °­Á¦·Î ÆÐÄ¡ÇÒ Áö ¹°¾îº»´Ù. 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: ¿©±â¿¡ ÄÁÆ®·Ñ ¾Ë¸² 󸮱â Äڵ带 Ãß°¡ÇÕ´Ï´Ù. 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) { // ½º·¹µå°¡ ÀÌ¹Ì µ¿ÀÛÁßÀÓ. ¿ø·¡ ¹öưÀ» ´©¸¦ ¼ö ¾øÀ¸´Ï // °¡º±°Ô ¾Ã¾îÁݽôÙ. } 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( _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 { // ½º·¹µå »ý¼º ¼º°ø bFailedAndCleanup = false; // È­¸éÀ» °»½ÅÇϵµ·Ï ŸÀ̸Ӹ¦ ¼¼ÆÃÇÑ´Ù. SetTimer(IID_PROGRESS_EXTRACT_SFXFILES, PROGRESS_UPDATE_TIME, NULL); // ÆÐÄ¡ ¹öưÀ» ´õ ¸ø ´©¸£µµ·Ï ÇÑ´Ù. 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); // ½º·¹µå°¡ Á¾·áµÇ¾úÀ½. 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: ¿©±â¿¡ ¸Þ½ÃÁö 󸮱â Äڵ带 Ãß°¡ ¹×/¶Ç´Â ±âº»°ªÀ» È£ÃâÇÕ´Ï´Ù. m_PatchFolderList.RemoveAll(); StopWorker(); CDialog::OnClose(); } void CPatchSFXDlg::OnBnClickedBtnPatchList() { // TODO: ¿©±â¿¡ ÄÁÆ®·Ñ ¾Ë¸² 󸮱â Äڵ带 Ãß°¡ÇÕ´Ï´Ù. // ÆÐÄ¡¸®½ºÆ® ÆÄÀÏÀ» ã¾Æ¼­ Àд´Ù. // ÆÄÀÏ¿¡¼­ Æú´õ¸®½ºÆ®¸¦ Àд´Ù. // ù¹øÂ° Æú´õ¸¦ ¿¡µ÷¹Ú½º¿¡ ¼¼ÆÃÇÑ´Ù. // ÆÐÄ¡ ¹öưÀ» ´©¸£°Ô ÇÑ´Ù. 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); // ÆÐÄ¡¸®½ºÆ®¿¡ ÆÐÄ¡°¡ ³²¾Æ ÀÖÀ¸¸é, ¶Ç ÆÐÄ¡¸¦ ÇÑ´Ù.. 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: ¿©±â¿¡ ÄÁÆ®·Ñ ¾Ë¸² 󸮱â Äڵ带 Ãß°¡ÇÕ´Ï´Ù. PostQuitMessage(0); }