| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974 |
- /*
- ** Command & Conquer Renegade(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** 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 3 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.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- // CommandoUpdateDlg.cpp : implementation file
- //
- #include "stdafx.h"
- #include "CommandoUpdate.h"
- #include "CommandoUpdateDlg.h"
- #include "FileCopyDialog.H"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- /////////////////////////////////////////////////////////////////////////////
- //
- // Data Tables
- //
- /////////////////////////////////////////////////////////////////////////////
- typedef struct
- {
- FileCopyDialogClass *dialog;
- CString src_dir;
- CString dest_dir;
- bool is_recursive;
- bool result;
- } UPDATE_INFO;
- typedef struct
- {
- LPCTSTR title;
- LPCTSTR src;
- LPCTSTR default_dir;
- LPCTSTR reg_key;
- UINT ctrl_id;
- UINT clean_ctrl_id;
- UINT dir_ctrl_id;
- bool clean_default;
- bool is_recursive;
- } APP_INFO;
- typedef enum
- {
- APP_EDITOR = 0,
- APP_GAME_ENGINE,
- APP_GAME_LEVELS,
- APP_GAME_MOVIES,
- APP_LIGHTMAP,
- APP_VISFARM,
- APP_MIXVIEW,
- APP_MULTIPLAY,
- APP_MAX,
- } APPLICATION_IDS;
- const APP_INFO APPLICATIONS[APP_MAX] =
- {
- { "Level Editor", "\\\\mobius\\project7\\projects\\renegade\\programming\\tools\\level edit", "c:\\commando\\leveledit", "LevelEdit\\Install", IDC_EDITOR_CHECK, IDC_EDITOR_CLEAN_CHECK, IDC_EDITOR_DIR_BUTTON, true, false },
- { "Game Engine", "\\\\havoc\\rock\\projects\\renegade\\asset management\\current build", "c:\\commando\\run", "Commando\\Install", IDC_GAME_CHECK, IDC_GAME_CLEAN_CHECK, IDC_GAME_DIR_BUTTON, false, true },
- { "Game Levels", "\\\\havoc\\rock\\projects\\renegade\\asset management\\current levels", "c:\\commando\\run", "Commando\\Install", IDC_GAME_LEVELS_CHECK, IDC_GAME_CLEAN_CHECK, IDC_GAME_DIR_BUTTON, false, true },
- { "Game Movies", "\\\\havoc\\rock\\projects\\renegade\\asset management\\cinematics", "c:\\commando\\run", "Commando\\Install", IDC_GAME_MOVIES_CHECK, IDC_GAME_CLEAN_CHECK, IDC_GAME_DIR_BUTTON, false, true },
- { "Lightmap", "\\\\mobius\\project7\\projects\\renegade\\programming\\tools\\lightmap", "c:\\commando\\lightmap", "LightMap\\Install", IDC_LIGHTMAP_CHECK, IDC_LIGHTMAP_CLEAN_CHECK, IDC_LIGHTMAP_DIR_BUTTON, true, false },
- { "Vis Farm", "\\\\mobius\\project7\\projects\\renegade\\programming\\tools\\vis farm", "c:\\commando\\vis farm", "VisFarm\\Install", IDC_VISFARM_CHECK, IDC_VISFARM_CLEAN_CHECK, IDC_VISFARM_DIR_BUTTON, false, false },
- { "Mix Viewer", "\\\\mobius\\project7\\projects\\renegade\\programming\\tools\\mixview", "c:\\commando\\mixview", "MixView\\Install", IDC_MIXVIEW_CHECK, IDC_MIXVIEW_CLEAN_CHECK, IDC_MIXVIEW_DIR_BUTTON, false, false },
- { "Multiplay", "\\\\tanya\\game\\projects\\renegade\\run", "c:\\renegade\\mplay", "MPlay\\Install", IDC_MULTIPLAY_CHECK, IDC_MULTIPLAY_CLEAN_CHECK, IDC_MULTIPLAY_DIR_BUTTON, false, true }
- };
- const char * const INSTALL_REG_VALUE = "Path";
- const char * const DATA_SUB_DIR = "\\Data";
- const char * const MOVIE_SUB_DIR = "\\Data\\Movies";
- const char * const SRDLL_SUB_DIR = "\\SrDLL";
- /////////////////////////////////////////////////////////////////////////////
- //
- // Local prototypes
- //
- /////////////////////////////////////////////////////////////////////////////
- bool Update_App (CWnd *parent_wnd, LPCTSTR title, LPCTSTR src_dir, LPCTSTR dest_dir, bool is_recursive);
- bool Clean_Directory (LPCTSTR local_dir, bool is_recursive);
- bool Get_Install_Directory (HWND hparent_wnd, LPCTSTR title, CString &folder);
- bool Delete_File (LPCTSTR filename);
- /////////////////////////////////////////////////////////////////////////////
- // CCommandoUpdateDlg dialog
- CCommandoUpdateDlg::CCommandoUpdateDlg(CWnd* pParent /*=NULL*/)
- : CDialog(CCommandoUpdateDlg::IDD, pParent)
- {
- //{{AFX_DATA_INIT(CCommandoUpdateDlg)
- // NOTE: the ClassWizard will add member initialization here
- //}}AFX_DATA_INIT
- // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
- m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
- }
- void CCommandoUpdateDlg::DoDataExchange(CDataExchange* pDX)
- {
- CDialog::DoDataExchange(pDX);
- //{{AFX_DATA_MAP(CCommandoUpdateDlg)
- // NOTE: the ClassWizard will add DDX and DDV calls here
- //}}AFX_DATA_MAP
- }
- BEGIN_MESSAGE_MAP(CCommandoUpdateDlg, CDialog)
- //{{AFX_MSG_MAP(CCommandoUpdateDlg)
- ON_WM_PAINT()
- ON_WM_QUERYDRAGICON()
- ON_BN_CLICKED(IDC_DEFAULTS, OnDefaults)
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
- /////////////////////////////////////////////////////////////////////////////
- // CCommandoUpdateDlg message handlers
- BOOL CCommandoUpdateDlg::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
- //
- // Check/uncheck the applications by default
- //
- for (int index = 0; index < APP_MAX; index ++) {
- const APP_INFO &app_info = APPLICATIONS[index];
- HKEY hreg_key = NULL;
- CString reg_key_name;
- reg_key_name.Format ("Software\\Westwood Studios\\%s", app_info.reg_key);
- TCHAR path[MAX_PATH] = { 0 };
- //
- // Is this application installed?
- //
- if (::RegOpenKeyEx (HKEY_CURRENT_USER, reg_key_name, 0L, KEY_READ, &hreg_key) == ERROR_SUCCESS) {
- SendDlgItemMessage (app_info.ctrl_id, BM_SETCHECK, (WPARAM)TRUE);
-
- //
- // Read the installation directory from the registry
- //
- DWORD size = sizeof (path);
- ::RegQueryValueEx (hreg_key, INSTALL_REG_VALUE, 0L, NULL, (BYTE *)path, &size);
- ::RegCloseKey (hreg_key);
- } else {
- ::EnableWindow (::GetDlgItem (m_hWnd, app_info.clean_ctrl_id), false);
- ::EnableWindow (::GetDlgItem (m_hWnd, app_info.dir_ctrl_id), false);
- }
- //
- // Set the text of the install directory buttons
- //
- if (path[0] == 0) {
- ::lstrcpy (path, app_info.default_dir);
- }
- SetDlgItemText (app_info.dir_ctrl_id, path);
- //
- // Check the clean option (by default) if necessary
- //
- if (app_info.clean_default) {
- SendDlgItemMessage (app_info.clean_ctrl_id, BM_SETCHECK, (WPARAM)TRUE);
- }
- }
- return TRUE;
- }
- // 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 CCommandoUpdateDlg::OnPaint()
- {
- if (IsIconic())
- {
- CPaintDC dc(this); // device context for painting
- SendMessage(WM_ICONERASEBKGND, (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 to obtain the cursor to display while the user drags
- // the minimized window.
- HCURSOR CCommandoUpdateDlg::OnQueryDragIcon()
- {
- return (HCURSOR) m_hIcon;
- }
- //////////////////////////////////////////////////////////////////////////////////
- //
- // OnOK
- //
- //////////////////////////////////////////////////////////////////////////////////
- void
- CCommandoUpdateDlg::OnOK (void)
- {
- //
- // Install/upgrade each application
- //
- bool success = true;
- for (int index = 0; (index < APP_MAX) && success; index ++) {
- const APP_INFO &app_info = APPLICATIONS[index];
- //
- // Does the user want to install this application?
- //
- if (SendDlgItemMessage (app_info.ctrl_id, BM_GETCHECK) == 1) {
- HKEY hreg_key = NULL;
- CString reg_key_name;
- reg_key_name.Format ("Software\\Westwood Studios\\%s", app_info.reg_key);
- //
- // Get the path where this application is installed
- //
- CString local_path;
- GetDlgItemText (app_info.dir_ctrl_id, local_path);
- // Ensure the path doesn't contain a terminating delimiter
- if (local_path[::lstrlen (local_path) - 1] == '\\') {
- local_path.Delete (::lstrlen (local_path) - 1, 1);
- }
- if (success) {
- CWaitCursor wait_cursor;
- //
- // Clean the old version if necessary
- //
- if (SendDlgItemMessage (app_info.clean_ctrl_id, BM_GETCHECK) == 1) {
- //
- // Special case the "game engine only" option. Note: we only want
- // to clean the data subdir if we aren't cleaning the game directory
- //
- if (index == APP_GAME_LEVELS || index == APP_GAME_MOVIES) {
- if (SendDlgItemMessage (APPLICATIONS[APP_GAME_ENGINE].ctrl_id, BM_GETCHECK) == 0) {
-
- if (index == APP_GAME_MOVIES) {
- CString data_dir = local_path + MOVIE_SUB_DIR;
- ::Clean_Directory (data_dir, app_info.is_recursive);
- } else {
- CString data_dir = local_path + DATA_SUB_DIR;
- ::Clean_Directory (data_dir, app_info.is_recursive);
- }
- }
- } else {
- ::Clean_Directory (local_path, app_info.is_recursive);
- }
- }
-
- //
- // Special case the "game levels" option
- //
- if (index == APP_GAME_LEVELS) {
- CString data_dir = local_path + DATA_SUB_DIR;
- CString src_data_dir = app_info.src;
- CString data_title = "Game Levels";
- success &= ::Update_App (this, data_title, src_data_dir, data_dir, app_info.is_recursive);
- } else if (index == APP_GAME_MOVIES) {
- CString data_dir = local_path + MOVIE_SUB_DIR;
- CString src_data_dir = app_info.src;
- CString data_title = "Game Movies";
- success &= ::Update_App (this, data_title, src_data_dir, data_dir, app_info.is_recursive);
- } else {
-
- //
- // Update the application's files
- //
- success &= ::Update_App (this, app_info.title, app_info.src, local_path, app_info.is_recursive);
- }
-
- //
- // Write the app's installation dir to the registry if we
- // installed it correctly.
- //
- if (success) {
- success &= (::RegCreateKeyEx ( HKEY_CURRENT_USER,
- reg_key_name,
- 0L,
- NULL,
- REG_OPTION_NON_VOLATILE,
- KEY_ALL_ACCESS,
- NULL,
- &hreg_key,
- NULL) == ERROR_SUCCESS);
- if (success) {
- ::RegSetValueEx ( hreg_key,
- INSTALL_REG_VALUE,
- 0L,
- REG_SZ,
- (BYTE *)(LPCTSTR)local_path,
- local_path.GetLength () + 1);
- ::RegCloseKey (hreg_key);
- }
- }
- }
- }
- }
-
- CDialog::OnOK ();
- return ;
- }
- //////////////////////////////////////////////////////////////////////////////////
- //
- // Get_Install_Directory
- //
- //////////////////////////////////////////////////////////////////////////////////
- bool
- Get_Install_Directory (HWND hparent_wnd, LPCTSTR title, CString &folder)
- {
- bool retval = false;
- // Browse for the folder
- BROWSEINFO browse_info = { 0 };
- browse_info.hwndOwner = hparent_wnd;
- browse_info.lpszTitle = title;
- browse_info.ulFlags = BIF_RETURNONLYFSDIRS;
- LPITEMIDLIST pidl = ::SHBrowseForFolder (&browse_info);
- if (pidl != NULL) {
-
- // Convert the 'PIDL' into a string
- char path[MAX_PATH];
- retval = (::SHGetPathFromIDList (pidl, path) == TRUE);
- if (retval) {
- folder = path;
- }
- // Free the 'PIDL'
- LPMALLOC pmalloc = NULL;
- if (SUCCEEDED (::SHGetMalloc (&pmalloc))) {
- pmalloc->Free (pidl);
- pmalloc->Release ();
- }
- }
-
- //CFileDialog dialog (TRUE, ".pth", "test.pth", OFN_PATHMUSTEXIST | OFN_EXPLORER, "files *.*|*.*||", CWnd::FromHandle(hparent_wnd));
- //CFileDialog dialog (TRUE, ".pth", "test.pth", OFN_PATHMUSTEXIST | OFN_EXPLORER | OFN_ENABLETEMPLATEHANDLE, "files *.*|*.*||", CWnd::FromHandle(hparent_wnd));
- //dialog.m_ofn.lpTemplateName = MAKEINTRESOURCE (IDD_DIR_SELECT_DIALOG);
- //dialog.m_ofn.hInstance = ::AfxGetInstanceHandle ();
- //HRSRC resource = ::FindResource (::AfxGetInstanceHandle (), MAKEINTRESOURCE (IDD_DIR_SELECT_DIALOG), RT_DIALOG);
- //dialog.m_ofn.hInstance = (HINSTANCE)::LoadResource (::AfxGetInstanceHandle (), resource);
- //dialog.DoModal ();
- /*TCHAR path[MAX_PATH] = { 0 };
- OPENFILENAME ofn = { 0 };
- ofn.lStructSize = sizeof (ofn);
- ofn.Flags = OFN_PATHMUSTEXIST | OFN_ENABLETEMPLATE;
- ofn.hInstance = ::AfxGetInstanceHandle ();
- ofn.lpTemplateName = MAKEINTRESOURCE (IDD_DIR_SELECT_DIALOG);
- ofn.hwndOwner = hparent_wnd;
- ofn.lpstrFile = path;
- ofn.nMaxFile = sizeof (path);
- GetOpenFileName (&ofn);
- ::CommDlgExtendedError ();*/
- //retval = (dialog.DoModal () == IDOK);
- // Return the true/false result code
- return retval;
- }
- ////////////////////////////////////////////////////////////////////////////
- //
- // Strip_Filename_From_Path
- //
- ////////////////////////////////////////////////////////////////////////////
- CString
- Strip_Filename_From_Path (LPCTSTR path)
- {
- // Copy the path to a buffer we can modify
- TCHAR temp_path[MAX_PATH];
- ::lstrcpy (temp_path, path);
- // Find the last occurance of the directory deliminator
- LPTSTR filename = ::strrchr (temp_path, '\\');
- if (filename != NULL) {
- // Strip off the filename
- filename[0] = 0;
- }
- // Return the path only
- return CString (temp_path);
- }
- ////////////////////////////////////////////////////////////////////////////
- //
- // Delete_File
- //
- ////////////////////////////////////////////////////////////////////////////
- bool
- Delete_File (LPCTSTR filename)
- {
- // Assume failure
- bool retval = false;
- ASSERT (filename != NULL);
- if (filename != NULL) {
- // Strip the readonly bit off if necessary
- DWORD attributes = ::GetFileAttributes (filename);
- if ((attributes != 0xFFFFFFFF) &&
- ((attributes & FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY))
- {
- ::SetFileAttributes (filename, attributes & (~FILE_ATTRIBUTE_READONLY));
- }
- // Perform the delete operation!
- if ((attributes != 0xFFFFFFFF) &&
- ((attributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY))
- {
- retval = ::RemoveDirectory (filename) == TRUE;
- } else {
- retval = ::DeleteFile (filename) == TRUE;
- }
-
- }
- // Return the true/false result code
- return retval;
- }
- ////////////////////////////////////////////////////////////////////////////
- //
- // Copy_File
- //
- ////////////////////////////////////////////////////////////////////////////
- bool
- Copy_File
- (
- LPCTSTR existing_filename,
- LPCTSTR new_filename,
- bool bforce_copy
- )
- {
- // Assume failure
- bool retval = false;
- ASSERT (existing_filename != NULL);
- ASSERT (new_filename != NULL);
- if ((existing_filename != NULL) &&
- (new_filename != NULL)) {
- // Make sure we aren't copying over ourselves
- bool allow_copy = (::lstrcmpi (existing_filename, new_filename) != 0);
-
- // Strip the readonly bit off if necessary
- DWORD attributes = ::GetFileAttributes (new_filename);
- if (allow_copy &&
- (attributes != 0xFFFFFFFF) &&
- ((attributes & FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY)) {
- if (bforce_copy) {
- ::SetFileAttributes (new_filename, attributes & (~FILE_ATTRIBUTE_READONLY));
- } else {
- allow_copy = false;
- }
- }
- // Perform the copy operation!
- if (allow_copy) {
- retval = (::CopyFile (existing_filename, new_filename, FALSE) == TRUE);
- }
- }
- // Return the true/false result code
- return retval;
- }
- __inline void Delimit_Path (CString &path)
- {
- if (path[::lstrlen (path) - 1] != '\\') {
- path += CString ("\\");
- }
- return ;
- }
- //////////////////////////////////////////////////////////////////////////////////
- //
- // Clean_Directory
- //
- //////////////////////////////////////////////////////////////////////////////////
- bool
- Clean_Directory (LPCTSTR local_dir, bool is_recursive)
- {
- bool retval = true;
- // Build a search mask from the directory
- CString search_mask = CString (local_dir) + "\\*.*";
-
- // Loop through all the files in this directory and add them
- // to our list
- CStringList file_list;
- BOOL bcontinue = TRUE;
- WIN32_FIND_DATA find_info = { 0 };
- for (HANDLE hfind = ::FindFirstFile (search_mask, &find_info);
- (hfind != INVALID_HANDLE_VALUE) && bcontinue;
- bcontinue = ::FindNextFile (hfind, &find_info)) {
-
- // If this file isn't a directory, add it to the list
- if (!(find_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
- CString filename = find_info.cFileName;
- file_list.AddTail (filename);
- } else if (is_recursive && find_info.cFileName[0] != '.') {
-
- //
- // Recurse into this subdirectory
- //
- CString full_path = local_dir;
- ::Delimit_Path (full_path);
- full_path += find_info.cFileName;
- Clean_Directory (full_path, is_recursive);
-
- //
- // Add this directory to the list so it will get
- // deleted with the files...
- //
- CString filename = find_info.cFileName;
- file_list.AddTail (filename);
- }
- }
- // Close the search handle
- if (hfind != NULL) {
- ::FindClose (hfind);
- }
-
- //
- // Now loop through all the files and delete them
- //
- for (POSITION pos = file_list.GetHeadPosition (); pos != NULL; ) {
- CString &filename = file_list.GetNext (pos);
- CString full_path = local_dir + CString ("\\") + filename;
- if (::Delete_File (full_path) == FALSE) {
- CString message;
- message.Format ("Cannot delete %s. This may result in an incomplete update. Please make sure no applications are running before running the update.", full_path);
- ::MessageBox (NULL, message, "Delete Error", MB_SETFOREGROUND | MB_TOPMOST | MB_ICONEXCLAMATION | MB_OK);
- retval = false;
- }
- }
- return retval;
- }
- //////////////////////////////////////////////////////////////////////////////////
- //
- // Create_Dir_If_Necessary
- //
- //////////////////////////////////////////////////////////////////////////////////
- void
- Create_Dir_If_Necessary (LPCTSTR path)
- {
- if (::GetFileAttributes (path) == 0xFFFFFFFF) {
- Create_Dir_If_Necessary (::Strip_Filename_From_Path (path));
- ::CreateDirectory (path, NULL);
- }
-
- return ;
- }
- //////////////////////////////////////////////////////////////////////////////////
- //
- // Build_File_List
- //
- //////////////////////////////////////////////////////////////////////////////////
- void
- Build_File_List (LPCTSTR search_path, CStringList &file_list)
- {
- //
- // Loop through all the files in this directory and add them
- // to our list
- //
- BOOL keep_going = TRUE;
- WIN32_FIND_DATA find_info = { 0 };
- for (HANDLE hfind = ::FindFirstFile (search_path, &find_info);
- (hfind != INVALID_HANDLE_VALUE) && keep_going;
- keep_going = ::FindNextFile (hfind, &find_info))
- {
- //
- // If this file isn't a directory, add it to the list
- //
- if (!(find_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
- CString filename = find_info.cFileName;
- file_list.AddTail (filename);
- }
- }
- // Close the search handle
- if (hfind != NULL) {
- ::FindClose (hfind);
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////
- //
- // Quick_Compare_Files
- //
- ////////////////////////////////////////////////////////////////////////////
- int
- Quick_Compare_Files
- (
- LPCTSTR file1,
- LPCTSTR file2
- )
- {
- // Assume they are the same
- int compare = 0;
- // Params OK?
- ASSERT (file1 != NULL);
- ASSERT (file2 != NULL);
- if ((file1 != NULL) && (file2 != NULL)) {
- // Attempt to open file1
- HANDLE hfile1 = ::CreateFile (file1,
- 0,
- 0,
- NULL,
- OPEN_EXISTING,
- 0L,
- NULL);
- // Attempt to open file2
- HANDLE hfile2 = ::CreateFile (file2,
- 0,
- 0,
- NULL,
- OPEN_EXISTING,
- 0L,
- NULL);
- if ((hfile1 != INVALID_HANDLE_VALUE) && (hfile2 != INVALID_HANDLE_VALUE)) {
- // Get information about these 2 files.
- BY_HANDLE_FILE_INFORMATION file1_info = { 0 };
- BY_HANDLE_FILE_INFORMATION file2_info = { 0 };
- ::GetFileInformationByHandle (hfile1, &file1_info);
- ::GetFileInformationByHandle (hfile2, &file2_info);
- // Compare the time these files were last written to
- compare = ::CompareFileTime (&file1_info.ftLastWriteTime, &file2_info.ftLastWriteTime);
- } else if ((hfile1 == INVALID_HANDLE_VALUE) && (hfile2 != INVALID_HANDLE_VALUE)) {
- compare = -1;
- } else if ((hfile1 != INVALID_HANDLE_VALUE) && (hfile2 == INVALID_HANDLE_VALUE)) {
- compare = 1;
- }
-
- if (hfile1 != INVALID_HANDLE_VALUE) {
- ::CloseHandle (hfile1);
- }
- if (hfile2 != INVALID_HANDLE_VALUE) {
- ::CloseHandle (hfile2);
- }
- }
- // Same as strcmp, -1 if file1 is older than file2, 0 if equal, 1 if file1 is newer than file2
- return compare;
- }
- //////////////////////////////////////////////////////////////////////////////////
- //
- // FileNeedsCopying
- //
- //////////////////////////////////////////////////////////////////////////////////
- bool
- FileNeedsCopying (LPCTSTR src_path, LPCTSTR dest_path)
- {
- return (Quick_Compare_Files (src_path, dest_path) != 0);
- }
- //////////////////////////////////////////////////////////////////////////////////
- //
- // Update_App_Directory
- //
- //////////////////////////////////////////////////////////////////////////////////
- bool
- Update_App_Directory
- (
- FileCopyDialogClass * dialog,
- LPCTSTR src_dir,
- LPCTSTR dest_dir,
- bool is_recursive
- )
- {
- bool retval = true;
- //
- // Build search masks from the src and dest directories
- //
- CString remote_search_mask = src_dir;
- remote_search_mask += "\\*.*";
- //
- // Loop through all the files in this directory and add them
- // to our list
- //
- BOOL keep_going = TRUE;
- WIN32_FIND_DATA find_info = { 0 };
- CStringList file_list;
- for (HANDLE hfind = ::FindFirstFile (remote_search_mask, &find_info);
- (hfind != INVALID_HANDLE_VALUE) && keep_going && retval;
- keep_going = ::FindNextFile (hfind, &find_info))
- {
- //
- // If this file isn't a directory, add it to the list
- //
- if (!(find_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
- CString filename = find_info.cFileName;
- file_list.AddTail (filename);
- } else if (is_recursive && find_info.cFileName[0] != '.') {
-
- //
- // Recurse into this subdirectory
- //
- CString full_src_path = src_dir;
- CString full_dest_path = dest_dir;
- ::Delimit_Path (full_src_path);
- ::Delimit_Path (full_dest_path);
- full_src_path += find_info.cFileName;
- full_dest_path += find_info.cFileName;
-
- retval &= ::Update_App_Directory ( dialog,
- full_src_path,
- full_dest_path,
- is_recursive);
- }
- }
- // Close the search handle
- if (hfind != NULL) {
- ::FindClose (hfind);
- }
-
- //
- // Now loop through all the files and copy them to the src
- //
- for (POSITION pos = file_list.GetHeadPosition (); pos != NULL && retval; ) {
- CString &filename = file_list.GetNext (pos);
- CString src_file = src_dir + CString ("\\") + filename;
- CString dest_file = dest_dir + CString ("\\") + filename;
-
- //
- // Make sure the destination directory exists
- //
- ::Create_Dir_If_Necessary (dest_dir);
- //
- // Do a file comparison to determine whether or not to copy the file
- //
- if (::FileNeedsCopying (src_file, dest_file)) {
- //
- // Update the dialog
- //
- dialog->Set_Current_File (filename);
- //
- // Copy the file
- //
- if (::Copy_File (src_file, dest_file, true) == FALSE) {
- CString message;
- message.Format ("Cannot copy %s to %s. Please make sure no applications are running before running the update.", src_file, dest_file);
- ::MessageBox (NULL, message, "Copy Error", MB_SETFOREGROUND | MB_TOPMOST | MB_ICONEXCLAMATION | MB_OK);
- retval = false;
- }
- }
- }
-
- return retval;
- }
- //////////////////////////////////////////////////////////////////////////////////
- //
- // fnUpdateAppDirectory
- //
- //////////////////////////////////////////////////////////////////////////////////
- UINT
- fnUpdateAppDirectory (LPVOID pParam)
- {
- UPDATE_INFO *info = (UPDATE_INFO *)pParam;
- ASSERT (info != NULL);
- if (info != NULL) {
-
- //
- // Begin updating this directory...
- //
- info->result = ::Update_App_Directory ( info->dialog,
- info->src_dir,
- info->dest_dir,
- info->is_recursive);
- //
- // Kill the updating dialog
- //
- ::PostMessage (info->dialog->m_hWnd, WM_USER + 101, 0, 0L);
- }
- return 1;
- }
- //////////////////////////////////////////////////////////////////////////////////
- //
- // Update_App
- //
- //////////////////////////////////////////////////////////////////////////////////
- bool
- Update_App
- (
- CWnd * parent_wnd,
- LPCTSTR title,
- LPCTSTR src_dir,
- LPCTSTR dest_dir,
- bool is_recursive
- )
- {
- CWaitCursor wait_cursor;
- FileCopyDialogClass dialog (parent_wnd);
- dialog.Set_Current_Application (title);
-
- //
- // Kick off a worker thread to do the actual file copy
- //
- UPDATE_INFO *info = new UPDATE_INFO;
- info->dialog = &dialog;
- info->src_dir = src_dir;
- info->dest_dir = dest_dir;
- info->is_recursive = is_recursive;
- ::AfxBeginThread (fnUpdateAppDirectory, (LPVOID)info);
-
- //
- // Display a dialog to monitor the progress
- //
- dialog.DoModal ();
- bool retval = info->result;
- delete info;
- return retval;
- }
- //////////////////////////////////////////////////////////////////////////////////
- //
- // OnCommand
- //
- //////////////////////////////////////////////////////////////////////////////////
- BOOL
- CCommandoUpdateDlg::OnCommand
- (
- WPARAM wParam,
- LPARAM lParam
- )
- {
- bool found = false;
- for (int index = 0; (index < APP_MAX) && (found == false); index ++) {
- const APP_INFO &app_info = APPLICATIONS[index];
- if (LOWORD (wParam) == app_info.ctrl_id) {
- bool enable = (SendDlgItemMessage (LOWORD(wParam), BM_GETCHECK) == 1);
- if (index == APP_GAME_ENGINE) {
- enable |= (SendDlgItemMessage (APPLICATIONS[APP_GAME_LEVELS].ctrl_id, BM_GETCHECK) == 1);
- enable |= (SendDlgItemMessage (APPLICATIONS[APP_GAME_MOVIES].ctrl_id, BM_GETCHECK) == 1);
- } else if (index == APP_GAME_LEVELS || index == APP_GAME_MOVIES) {
- enable |= (SendDlgItemMessage (APPLICATIONS[APP_GAME_ENGINE].ctrl_id, BM_GETCHECK) == 1);
- }
- //
- // Enable or disable the clean and directory buttons
- //
- ::EnableWindow (::GetDlgItem (m_hWnd, app_info.clean_ctrl_id), enable);
- ::EnableWindow (::GetDlgItem (m_hWnd, app_info.dir_ctrl_id), enable);
-
- } else if (LOWORD (wParam) == app_info.dir_ctrl_id) {
-
- //
- // Change the installation directoy
- //
- CString directory;
- CString dlg_title;
- dlg_title.Format ("Select a directory to install the %s to.", app_info.title);
- if (Get_Install_Directory (m_hWnd, dlg_title, directory)) {
- SetDlgItemText (app_info.dir_ctrl_id, directory);
- }
- found = true;
- }
- }
- return CDialog::OnCommand(wParam, lParam);
- }
- //////////////////////////////////////////////////////////////////////////////////
- //
- // OnDefaults
- //
- //////////////////////////////////////////////////////////////////////////////////
- void
- CCommandoUpdateDlg::OnDefaults (void)
- {
- for (int index = 0; index < APP_MAX; index ++) {
- const APP_INFO &app_info = APPLICATIONS[index];
- if (SendDlgItemMessage (app_info.ctrl_id, BM_GETCHECK) != 0) {
- SetDlgItemText (app_info.dir_ctrl_id, app_info.default_dir);
- }
- }
-
- return ;
- }
|