DWORD ProgressDialog::UpgradeAsync() {
  typedef std::list<CString> BackupFiles;

  CZipArchive ar;
  if (!ar.Open(upgradeFilePath_)) {
    ::PostMessage(m_hWnd, WM_UPGRADE_DONE, FALSE, 0);
    return 0;
  }

  bool copySuccess = true;
  TCHAR filePath[MAX_PATH];
  BackupFiles backupFiles;
  WORD fileCount = ar.GetCount();
  for (WORD i = 0; i < fileCount; i++) {
    CZipFileHeader *fileInfo = ar.GetFileInfo(i);
    if (fileInfo->IsDirectory()) {
      continue;
    }
    const CZipString &fileName = fileInfo->GetFileName();
    _tcscpy(filePath, appDir_);
    PathAddBackslash(filePath);
    _tcscat(filePath, fileName);
    if (PathFileExists(filePath)) {
      TCHAR backupFilePath[MAX_PATH];
      _tcscpy(backupFilePath, appDir_);
      PathAddBackslash(backupFilePath);
      _tcscat(backupFilePath, fileName);
      _tcscat(backupFilePath, _T(".bak"));
      if (PathFileExists(backupFilePath)) {
        DeleteFile(backupFilePath);
      }
      if (!MoveFile(filePath, backupFilePath)) {
        copySuccess = false;
        break;
      }
      backupFiles.push_back((LPCTSTR)fileName);
    }
    if (!ar.ExtractFile(i, appDir_)) {
      copySuccess = false;
      break;
    }
  }
  
  if (copySuccess) {
    AfxGetApp()->WriteProfileString(_T(""), _T("Version"), appVersion_);

    // remove backup files.
    for (BackupFiles::const_iterator i = backupFiles.begin(); i != backupFiles.end(); ++i) {
      TCHAR backupFilePath[MAX_PATH];
      _tcscpy(backupFilePath, appDir_);
      PathAddBackslash(backupFilePath);
      _tcscat(backupFilePath, *i);
      _tcscat(backupFilePath, _T(".bak"));

      DeleteFile(backupFilePath);
    }
  } else {
    // upgrade failed, restore backup.
    for (BackupFiles::const_iterator i = backupFiles.begin(); i != backupFiles.end(); ++i) {
      TCHAR backupFilePath[MAX_PATH];
      _tcscpy(backupFilePath, appDir_);
      PathAddBackslash(backupFilePath);
      _tcscat(backupFilePath, *i);
      _tcscat(backupFilePath, _T(".bak"));

      TCHAR filePath[MAX_PATH];
      _tcscpy(filePath, appDir_);
      PathAddBackslash(filePath);
      _tcscat(filePath, *i);

      DeleteFile(filePath);
      MoveFile(backupFilePath, filePath);
    }
  }

  ::PostMessage(m_hWnd, WM_UPGRADE_DONE, TRUE, 0);

  return 0;
}