W3DUpdateDlg.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. // W3DUpdateDlg.cpp : implementation file
  19. //
  20. #include "stdafx.h"
  21. #include "W3DUpdate.h"
  22. #include "W3DUpdateDlg.h"
  23. #include "FileCopyDialog.H"
  24. #ifdef _DEBUG
  25. #define new DEBUG_NEW
  26. #undef THIS_FILE
  27. static char THIS_FILE[] = __FILE__;
  28. #endif
  29. /////////////////////////////////////////////////////////////////////////////
  30. //
  31. // Data Tables
  32. //
  33. /////////////////////////////////////////////////////////////////////////////
  34. typedef struct
  35. {
  36. FileCopyDialogClass *dialog;
  37. CString src_dir;
  38. CString dest_dir;
  39. bool result;
  40. } UPDATE_INFO;
  41. typedef struct
  42. {
  43. LPCTSTR title;
  44. LPCTSTR src;
  45. LPCTSTR default_dir;
  46. LPCTSTR reg_key;
  47. UINT ctrl_id;
  48. UINT clean_ctrl_id;
  49. UINT dir_ctrl_id;
  50. bool clean_default;
  51. int copy_to_app_dir1;
  52. int copy_to_app_dir2;
  53. } APP_INFO;
  54. typedef enum
  55. {
  56. APP_VIEWER = 0,
  57. APP_PLUGIN,
  58. APP_WDUMP,
  59. APP_MAX4_PLUGIN,
  60. APP_RENEGADE_DAZZLES,
  61. APP_W3DSHELLEXT,
  62. APP_GMAXRENX,
  63. APP_MAX,
  64. } APPLICATION_IDS;
  65. const APP_INFO APPLICATIONS[APP_MAX] =
  66. // --- Title --- ---Source --- --Default Dir--- ---RegKey--- ---Ctrl_ID--- ---Clean CtrlID-- --Dir CtrlID--- --Clean default- copy to appdir1, copy to appdir2
  67. {
  68. { "W3DViewer", "\\\\cabal\\mis\\r&d\\w3d\\w3dview", "c:\\w3d\\w3dview", "W3DUpdate\\W3DView", IDC_VIEWER_CHECK, IDC_VIEWER_CLEAN_CHECK, IDC_VIEWER_DIR_BUTTON, true, -1, -1 },
  69. { "Max3 Plugin", "\\\\cabal\\mis\\r&d\\w3d\\maxplugins\\max3", "c:\\3dsmax3\\plugins\\westwood", "W3DUpdate\\MaxPlugin30", IDC_PLUGIN_CHECK, IDC_PLUGIN_CLEAN_CHECK, IDC_PLUGIN_DIR_BUTTON, false, -1, -1 },
  70. { "WDump", "\\\\cabal\\mis\\r&d\\w3d\\wdump", "c:\\w3d\\wdump", "W3DUpdate\\WDump", IDC_WDUMP_CHECK, IDC_WDUMP_CLEAN_CHECK, IDC_WDUMP_DIR_BUTTON, true, -1, -1 },
  71. { "Max4 Plugin", "\\\\cabal\\mis\\r&d\\w3d\\maxplugins\\max4", "c:\\3dsmax4\\plugins\\westwood", "W3DUpdate\\MaxPlugin40", IDC_MAX4_PLUGIN_CHECK, IDC_MAX4_PLUGIN_CLEAN_CHECK, IDC_MAX4_PLUGIN_DIR_BUTTON, false, -1, -1 },
  72. { "Renegade Dazzles", "\\\\mobius\\project7\\projects\\renegade\\asset management\\assets\\dazzle", "", "W3DUpdate\\Reneg Dazzle", IDC_RENEGDAZZLE_CHECK, -1, -1 , false, APP_VIEWER, APP_PLUGIN },
  73. { "W3D Shell Extension","\\\\cabal\\mis\\r&d\\w3d\\W3DShellExt", "", "W3DUpdate\\W3DShellExt", IDC_W3DSHELLEXT, -1 , -1 , false, -1, -1 },
  74. {"Gmax Settings", "\\\\cabal\\mis\\r&d\\w3d\\GmaxRenX", "", "W3DUpdate\\GmaxRenX", IDC_GMAX_CHECK, IDC_GMAX_CLEAN_CHECK2 , -1 , false, -1, -1}
  75. };
  76. const char * const INSTALL_REG_VALUE = "Path";
  77. /////////////////////////////////////////////////////////////////////////////
  78. //
  79. // Local prototypes
  80. //
  81. /////////////////////////////////////////////////////////////////////////////
  82. bool Update_App (CWnd *parent_wnd, LPCTSTR title, LPCTSTR src_dir, LPCTSTR dest_dir);
  83. bool Clean_Directory (LPCTSTR local_dir);
  84. bool Get_Install_Directory (HWND hparent_wnd, LPCTSTR title, CString &folder);
  85. bool Delete_File (LPCTSTR filename);
  86. /////////////////////////////////////////////////////////////////////////////
  87. // CW3DUpdateDlg dialog
  88. CW3DUpdateDlg::CW3DUpdateDlg(CWnd* pParent /*=NULL*/)
  89. : CDialog(CW3DUpdateDlg::IDD, pParent)
  90. {
  91. //{{AFX_DATA_INIT(CW3DUpdateDlg)
  92. // NOTE: the ClassWizard will add member initialization here
  93. //}}AFX_DATA_INIT
  94. // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
  95. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  96. }
  97. void CW3DUpdateDlg::DoDataExchange(CDataExchange* pDX)
  98. {
  99. CDialog::DoDataExchange(pDX);
  100. //{{AFX_DATA_MAP(CW3DUpdateDlg)
  101. // NOTE: the ClassWizard will add DDX and DDV calls here
  102. //}}AFX_DATA_MAP
  103. }
  104. BEGIN_MESSAGE_MAP(CW3DUpdateDlg, CDialog)
  105. //{{AFX_MSG_MAP(CW3DUpdateDlg)
  106. ON_WM_PAINT()
  107. ON_WM_QUERYDRAGICON()
  108. ON_BN_CLICKED(IDC_DEFAULTS, OnDefaults)
  109. //}}AFX_MSG_MAP
  110. END_MESSAGE_MAP()
  111. /////////////////////////////////////////////////////////////////////////////
  112. // CW3DUpdateDlg message handlers
  113. BOOL CW3DUpdateDlg::OnInitDialog()
  114. {
  115. CDialog::OnInitDialog();
  116. // Set the icon for this dialog. The framework does this automatically
  117. // when the application's main window is not a dialog
  118. SetIcon(m_hIcon, TRUE); // Set big icon
  119. SetIcon(m_hIcon, FALSE); // Set small icon
  120. //
  121. // Check/uncheck the applications by default
  122. //
  123. for (int index = 0; index < APP_MAX; index ++) {
  124. const APP_INFO &app_info = APPLICATIONS[index];
  125. HKEY hreg_key = NULL;
  126. CString reg_key_name;
  127. reg_key_name.Format ("Software\\Westwood Studios\\%s", app_info.reg_key);
  128. TCHAR path[MAX_PATH] = { 0 };
  129. //
  130. // Is this application installed?
  131. //
  132. if (::RegOpenKeyEx (HKEY_CURRENT_USER, reg_key_name, 0L, KEY_READ, &hreg_key) == ERROR_SUCCESS) {
  133. //Moumine-
  134. //SendDlgItemMessage (app_info.ctrl_id, BM_SETCHECK, (WPARAM)TRUE);
  135. //
  136. // Read the installation directory from the registry
  137. //
  138. DWORD size = sizeof (path);
  139. ::RegQueryValueEx (hreg_key, INSTALL_REG_VALUE, 0L, NULL, (BYTE *)path, &size);
  140. ::RegCloseKey (hreg_key);
  141. } else {
  142. ::EnableWindow (::GetDlgItem (m_hWnd, app_info.clean_ctrl_id), false);
  143. ::EnableWindow (::GetDlgItem (m_hWnd, app_info.dir_ctrl_id), false);
  144. }
  145. //
  146. // Set the text of the install directory buttons
  147. //
  148. if (path[0] == 0) {
  149. ::lstrcpy (path, app_info.default_dir);
  150. }
  151. if (app_info.dir_ctrl_id != -1) {
  152. SetDlgItemText (app_info.dir_ctrl_id, path);
  153. }
  154. //
  155. // Check the clean option (by default) if necessary
  156. //
  157. if (app_info.clean_default && app_info.clean_ctrl_id != -1) {
  158. SendDlgItemMessage (app_info.clean_ctrl_id, BM_SETCHECK, (WPARAM)TRUE);
  159. }
  160. }
  161. return TRUE;
  162. }
  163. // If you add a minimize button to your dialog, you will need the code below
  164. // to draw the icon. For MFC applications using the document/view model,
  165. // this is automatically done for you by the framework.
  166. void CW3DUpdateDlg::OnPaint()
  167. {
  168. if (IsIconic())
  169. {
  170. CPaintDC dc(this); // device context for painting
  171. SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
  172. // Center icon in client rectangle
  173. int cxIcon = GetSystemMetrics(SM_CXICON);
  174. int cyIcon = GetSystemMetrics(SM_CYICON);
  175. CRect rect;
  176. GetClientRect(&rect);
  177. int x = (rect.Width() - cxIcon + 1) / 2;
  178. int y = (rect.Height() - cyIcon + 1) / 2;
  179. // Draw the icon
  180. dc.DrawIcon(x, y, m_hIcon);
  181. }
  182. else
  183. {
  184. CDialog::OnPaint();
  185. }
  186. }
  187. // The system calls this to obtain the cursor to display while the user drags
  188. // the minimized window.
  189. HCURSOR CW3DUpdateDlg::OnQueryDragIcon()
  190. {
  191. return (HCURSOR) m_hIcon;
  192. }
  193. //////////////////////////////////////////////////////////////////////////////////
  194. //
  195. // OnOK
  196. //
  197. //////////////////////////////////////////////////////////////////////////////////
  198. void
  199. CW3DUpdateDlg::OnOK (void)
  200. {
  201. //
  202. // Install/upgrade each application
  203. //
  204. bool success = true;
  205. for (int index = 0; (index < APP_MAX) && success; index ++) {
  206. const APP_INFO &app_info = APPLICATIONS[index];
  207. //
  208. // Does the user want to install this application?
  209. //
  210. if (SendDlgItemMessage (app_info.ctrl_id, BM_GETCHECK) == 1) {
  211. //
  212. // Build a string containing the name registry key we will keep information
  213. // about this application in.
  214. //
  215. CString reg_key_name;
  216. reg_key_name.Format ("Software\\Westwood Studios\\%s", app_info.reg_key);
  217. //
  218. // Should we install this application to the same directory as another
  219. // application in the list?
  220. //
  221. if (app_info.copy_to_app_dir1 != -1) {
  222. CString local_path;
  223. //
  224. // Install the application to the same directory as App1
  225. //
  226. Get_Destination_Path (app_info.copy_to_app_dir1, local_path);
  227. success = Install_App (app_info.title, app_info.src, local_path, reg_key_name, false);
  228. if (success) {
  229. if (app_info.copy_to_app_dir2 != -1) {
  230. //
  231. // Install the application to the same directory as App2
  232. //
  233. Get_Destination_Path (app_info.copy_to_app_dir2, local_path);
  234. success = Install_App (app_info.title, app_info.src, local_path, reg_key_name, false);
  235. }
  236. }
  237. } else {
  238. //
  239. // Do we need to clean the source directory for this application?
  240. //
  241. bool clean = (SendDlgItemMessage (app_info.clean_ctrl_id, BM_GETCHECK) == 1);
  242. //
  243. // Get the path where this application is installed
  244. //
  245. CString local_path;
  246. Get_Destination_Path (index, local_path);
  247. //
  248. // Install the application
  249. //
  250. success = Install_App (app_info.title, app_info.src, local_path, reg_key_name, clean);
  251. }
  252. if(index == APP_W3DSHELLEXT){ //Need more registration
  253. RegisterShellExt();
  254. }else{
  255. if(index == APP_VIEWER){
  256. //Set Viewer as default application
  257. RegisterViewer(index);
  258. }
  259. }
  260. }
  261. }
  262. CDialog::OnOK ();
  263. return ;
  264. }
  265. //////////////////////////////////////////////////////////////////////////////////
  266. //
  267. // Get_Destination_Path
  268. //
  269. //////////////////////////////////////////////////////////////////////////////////
  270. void
  271. CW3DUpdateDlg::Get_Destination_Path (int app_id, CString &dest_path)
  272. {
  273. //
  274. // Read the destination directory from the dialog
  275. //
  276. switch(app_id){
  277. case APP_W3DSHELLEXT:{
  278. //SHGetFolderPath(NULL,CSIDL_SYSTEM, NULL,SHGFP_TYPE_CURRENT,dest_path.GetBuffer(MAX_PATH) );
  279. SHGetSpecialFolderPath(NULL,dest_path.GetBuffer(MAX_PATH), CSIDL_SYSTEM, TRUE);
  280. dest_path.ReleaseBuffer();
  281. break;
  282. }
  283. case APP_GMAXRENX:{
  284. GetEnvironmentVariable("GMaxLoc", dest_path.GetBuffer(MAX_PATH),MAX_PATH);
  285. dest_path.ReleaseBuffer();
  286. CString str(MAKEINTRESOURCE(IDS_GMAXRENX_PATH));
  287. dest_path += str;
  288. break;
  289. }
  290. default:{
  291. GetDlgItemText (APPLICATIONS[app_id].dir_ctrl_id, dest_path);
  292. break;
  293. }
  294. }
  295. //
  296. // Ensure the path doesn't contain a terminating delimiter
  297. //
  298. if (dest_path[::lstrlen (dest_path) - 1] == '\\') {
  299. dest_path.Delete (::lstrlen (dest_path) - 1, 1);
  300. }
  301. return ;
  302. }
  303. //////////////////////////////////////////////////////////////////////////////////
  304. //
  305. // Install_App
  306. //
  307. //////////////////////////////////////////////////////////////////////////////////
  308. bool
  309. CW3DUpdateDlg::Install_App
  310. (
  311. const CString &title,
  312. const CString &src_path,
  313. const CString &dest_path,
  314. const CString &reg_key_name,
  315. bool clean
  316. )
  317. {
  318. CWaitCursor wait_cursor;
  319. //
  320. // Clean the old version if necessary
  321. //
  322. if (clean) {
  323. ::Clean_Directory (dest_path);
  324. }
  325. //
  326. // Update the application's files
  327. //
  328. bool ret_val = ::Update_App (this, title, src_path, dest_path);
  329. //
  330. // Write the app's installation dir to the registry if we
  331. // installed it correctly.
  332. //
  333. if (ret_val) {
  334. HKEY reg_key = NULL;
  335. ret_val &= (::RegCreateKeyEx ( HKEY_CURRENT_USER,
  336. reg_key_name,
  337. 0L,
  338. NULL,
  339. REG_OPTION_NON_VOLATILE,
  340. KEY_ALL_ACCESS,
  341. NULL,
  342. &reg_key,
  343. NULL) == ERROR_SUCCESS);
  344. if (ret_val) {
  345. ::RegSetValueEx ( reg_key,
  346. INSTALL_REG_VALUE,
  347. 0L,
  348. REG_SZ,
  349. (BYTE *)(LPCTSTR)dest_path,
  350. dest_path.GetLength () + 1);
  351. ::RegCloseKey (reg_key);
  352. }
  353. }
  354. return ret_val;
  355. }
  356. //////////////////////////////////////////////////////////////////////////////////
  357. //
  358. // Get_Install_Directory
  359. //
  360. //////////////////////////////////////////////////////////////////////////////////
  361. bool
  362. Get_Install_Directory (HWND hparent_wnd, LPCTSTR title, CString &folder)
  363. {
  364. bool ret_val = false;
  365. // Browse for the folder
  366. BROWSEINFO browse_info = { 0 };
  367. browse_info.hwndOwner = hparent_wnd;
  368. browse_info.lpszTitle = title;
  369. browse_info.ulFlags = BIF_RETURNONLYFSDIRS;
  370. LPITEMIDLIST pidl = ::SHBrowseForFolder (&browse_info);
  371. if (pidl != NULL) {
  372. // Convert the 'PIDL' into a string
  373. char path[MAX_PATH];
  374. ret_val = (::SHGetPathFromIDList (pidl, path) == TRUE);
  375. if (ret_val) {
  376. folder = path;
  377. }
  378. // Free the 'PIDL'
  379. LPMALLOC pmalloc = NULL;
  380. if (SUCCEEDED (::SHGetMalloc (&pmalloc))) {
  381. pmalloc->Free (pidl);
  382. pmalloc->Release ();
  383. }
  384. }
  385. //CFileDialog dialog (TRUE, ".pth", "test.pth", OFN_PATHMUSTEXIST | OFN_EXPLORER, "files *.*|*.*||", CWnd::FromHandle(hparent_wnd));
  386. //CFileDialog dialog (TRUE, ".pth", "test.pth", OFN_PATHMUSTEXIST | OFN_EXPLORER | OFN_ENABLETEMPLATEHANDLE, "files *.*|*.*||", CWnd::FromHandle(hparent_wnd));
  387. //dialog.m_ofn.lpTemplateName = MAKEINTRESOURCE (IDD_DIR_SELECT_DIALOG);
  388. //dialog.m_ofn.hInstance = ::AfxGetInstanceHandle ();
  389. //HRSRC resource = ::FindResource (::AfxGetInstanceHandle (), MAKEINTRESOURCE (IDD_DIR_SELECT_DIALOG), RT_DIALOG);
  390. //dialog.m_ofn.hInstance = (HINSTANCE)::LoadResource (::AfxGetInstanceHandle (), resource);
  391. //dialog.DoModal ();
  392. /*TCHAR path[MAX_PATH] = { 0 };
  393. OPENFILENAME ofn = { 0 };
  394. ofn.lStructSize = sizeof (ofn);
  395. ofn.Flags = OFN_PATHMUSTEXIST | OFN_ENABLETEMPLATE;
  396. ofn.hInstance = ::AfxGetInstanceHandle ();
  397. ofn.lpTemplateName = MAKEINTRESOURCE (IDD_DIR_SELECT_DIALOG);
  398. ofn.hwndOwner = hparent_wnd;
  399. ofn.lpstrFile = path;
  400. ofn.nMaxFile = sizeof (path);
  401. GetOpenFileName (&ofn);
  402. ::CommDlgExtendedError ();*/
  403. //ret_val = (dialog.DoModal () == IDOK);
  404. // Return the true/false result code
  405. return ret_val;
  406. }
  407. ////////////////////////////////////////////////////////////////////////////
  408. //
  409. // Strip_Filename_From_Path
  410. //
  411. ////////////////////////////////////////////////////////////////////////////
  412. CString
  413. Strip_Filename_From_Path (LPCTSTR path)
  414. {
  415. // Copy the path to a buffer we can modify
  416. TCHAR temp_path[MAX_PATH];
  417. ::lstrcpy (temp_path, path);
  418. // Find the last occurance of the directory deliminator
  419. LPTSTR filename = ::strrchr (temp_path, '\\');
  420. if (filename != NULL) {
  421. // Strip off the filename
  422. filename[0] = 0;
  423. }
  424. // Return the path only
  425. return CString (temp_path);
  426. }
  427. ////////////////////////////////////////////////////////////////////////////
  428. //
  429. // Delete_File
  430. //
  431. ////////////////////////////////////////////////////////////////////////////
  432. bool
  433. Delete_File (LPCTSTR filename)
  434. {
  435. // Assume failure
  436. bool ret_val = false;
  437. ASSERT (filename != NULL);
  438. if (filename != NULL) {
  439. // Strip the readonly bit off if necessary
  440. DWORD attributes = ::GetFileAttributes (filename);
  441. if ((attributes != 0xFFFFFFFF) &&
  442. ((attributes & FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY)) {
  443. ::SetFileAttributes (filename, attributes & (~FILE_ATTRIBUTE_READONLY));
  444. }
  445. // Perform the delete operation!
  446. ret_val = ::DeleteFile (filename) == TRUE;
  447. }
  448. // Return the true/false result code
  449. return ret_val;
  450. }
  451. ////////////////////////////////////////////////////////////////////////////
  452. //
  453. // Copy_File
  454. //
  455. ////////////////////////////////////////////////////////////////////////////
  456. bool
  457. Copy_File
  458. (
  459. LPCTSTR existing_filename,
  460. LPCTSTR new_filename,
  461. bool bforce_copy
  462. )
  463. {
  464. // Assume failure
  465. bool ret_val = false;
  466. ASSERT (existing_filename != NULL);
  467. ASSERT (new_filename != NULL);
  468. if ((existing_filename != NULL) &&
  469. (new_filename != NULL)) {
  470. // Make sure we aren't copying over ourselves
  471. bool allow_copy = (::lstrcmpi (existing_filename, new_filename) != 0);
  472. // Strip the readonly bit off if necessary
  473. DWORD attributes = ::GetFileAttributes (new_filename);
  474. if (allow_copy &&
  475. (attributes != 0xFFFFFFFF) &&
  476. ((attributes & FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY)) {
  477. if (bforce_copy) {
  478. ::SetFileAttributes (new_filename, attributes & (~FILE_ATTRIBUTE_READONLY));
  479. } else {
  480. allow_copy = false;
  481. }
  482. }
  483. // Perform the copy operation!
  484. if (allow_copy) {
  485. ret_val = (::CopyFile (existing_filename, new_filename, FALSE) == TRUE);
  486. }
  487. }
  488. // Return the true/false result code
  489. return ret_val;
  490. }
  491. //////////////////////////////////////////////////////////////////////////////////
  492. //
  493. // Clean_Directory
  494. //
  495. //////////////////////////////////////////////////////////////////////////////////
  496. bool
  497. Clean_Directory (LPCTSTR local_dir)
  498. {
  499. bool ret_val = true;
  500. // Build a search mask from the directory
  501. CString search_mask = CString (local_dir) + "\\*.*";
  502. // Loop through all the files in this directory and add them
  503. // to our list
  504. WIN32_FIND_DATA find_info = { 0 };
  505. HANDLE hfind = ::FindFirstFile (search_mask, &find_info);
  506. if(hfind){
  507. while(FindNextFile(hfind, &find_info)){
  508. // If this file isn't a directory, add it to the list
  509. if(!(find_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
  510. CString full_path = local_dir + CString ("\\") + find_info.cFileName;
  511. if (::Delete_File (full_path) == FALSE) {
  512. CString message;
  513. 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);
  514. ::MessageBox (NULL, message, "Delete Error", MB_SETFOREGROUND | MB_TOPMOST | MB_ICONEXCLAMATION | MB_OK);
  515. ret_val = false;
  516. }
  517. }else{
  518. if( find_info.cFileName[0] != '.'){
  519. CString new_dir = CString(local_dir) + "\\" + CString(find_info.cFileName);
  520. Clean_Directory(new_dir.GetBuffer(new_dir.GetLength()));
  521. new_dir.ReleaseBuffer();
  522. RemoveDirectory(new_dir.GetBuffer(new_dir.GetLength()));
  523. new_dir.ReleaseBuffer();
  524. }
  525. }
  526. }
  527. ::FindClose (hfind);
  528. }
  529. return ret_val;
  530. }
  531. //////////////////////////////////////////////////////////////////////////////////
  532. //
  533. // Create_Dir_If_Necessary
  534. //
  535. //////////////////////////////////////////////////////////////////////////////////
  536. void
  537. Create_Dir_If_Necessary (LPCTSTR path)
  538. {
  539. if (::GetFileAttributes (path) == 0xFFFFFFFF) {
  540. Create_Dir_If_Necessary (::Strip_Filename_From_Path (path));
  541. ::CreateDirectory (path, NULL);
  542. }
  543. return ;
  544. }
  545. //////////////////////////////////////////////////////////////////////////////////
  546. //
  547. // fnUpdateAppDirectory
  548. //
  549. //////////////////////////////////////////////////////////////////////////////////
  550. UINT
  551. fnUpdateAppDirectory (LPVOID pParam)
  552. {
  553. static call_depth(0);
  554. UPDATE_INFO *info = (UPDATE_INFO *)pParam;
  555. ASSERT (info != NULL);
  556. if (info != NULL) {
  557. info->result = true;
  558. // Build a search mask from the directory
  559. CString search_mask = info->src_dir + "\\*.*";
  560. // Loop through all the files in this directory and add them
  561. // to our list
  562. WIN32_FIND_DATA find_info = { 0 };
  563. HANDLE hfind = ::FindFirstFile (search_mask, &find_info);
  564. if(hfind){
  565. while(FindNextFile(hfind, &find_info)){
  566. // If this file isn't a directory, add it to the list
  567. if (!(find_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
  568. CString src_path = info->src_dir + CString ("\\") + find_info.cFileName;
  569. CString dest_path = info->dest_dir + CString ("\\") + find_info.cFileName;
  570. ::Create_Dir_If_Necessary (info->dest_dir);
  571. //info->dialog->Set_Current_File (find_info.cFileName);
  572. if (::Copy_File (src_path, dest_path, true) == FALSE) {
  573. CString message;
  574. message.Format (IDS_COPYFAIL, src_path, dest_path);
  575. ::MessageBox (NULL, message, "Copy Error", MB_SETFOREGROUND | MB_TOPMOST | MB_ICONEXCLAMATION | MB_OK);
  576. info->result = false;
  577. }
  578. }else{
  579. if( find_info.cFileName[0] != '.'){
  580. UPDATE_INFO info2 = *info;
  581. CString folder = "\\";
  582. folder += find_info.cFileName;
  583. info2.dest_dir += folder;
  584. info2.src_dir += folder;
  585. call_depth ++;
  586. fnUpdateAppDirectory(&info2);
  587. call_depth --;
  588. }
  589. }
  590. }
  591. ::FindClose (hfind);
  592. }
  593. }
  594. if(!call_depth){
  595. // Kill the updating dialog
  596. ::PostMessage(info->dialog->m_hWnd, WM_USER + 101, 0, 0L);
  597. }
  598. return 1;
  599. }
  600. //////////////////////////////////////////////////////////////////////////////////
  601. //
  602. // Update_App
  603. //
  604. //////////////////////////////////////////////////////////////////////////////////
  605. bool
  606. Update_App
  607. (
  608. CWnd * parent_wnd,
  609. LPCTSTR title,
  610. LPCTSTR src_dir,
  611. LPCTSTR dest_dir
  612. )
  613. {
  614. CWaitCursor wait_cursor;
  615. FileCopyDialogClass dialog (parent_wnd);
  616. dialog.Set_Current_Application (title);
  617. //
  618. // Create the destination directory if necessary
  619. //
  620. if (::GetFileAttributes (dest_dir) == 0xFFFFFFFF) {
  621. ::CreateDirectory (dest_dir, NULL);
  622. }
  623. //
  624. // Kick off a worker thread to do the actual file copy
  625. //
  626. UPDATE_INFO *info = new UPDATE_INFO;
  627. info->dialog = &dialog;
  628. info->src_dir = src_dir;
  629. info->dest_dir = dest_dir;
  630. ::AfxBeginThread (fnUpdateAppDirectory, (LPVOID)info);
  631. // Kill the updating dialog
  632. ::PostMessage( dialog.m_hWnd, WM_USER + 101, 0, 0L);
  633. //
  634. // Display a dialog to monitor the progress
  635. //
  636. dialog.DoModal ();
  637. bool ret_val = info->result;
  638. delete info;
  639. return ret_val;
  640. }
  641. //////////////////////////////////////////////////////////////////////////////////
  642. //
  643. // OnCommand
  644. //
  645. //////////////////////////////////////////////////////////////////////////////////
  646. BOOL
  647. CW3DUpdateDlg::OnCommand
  648. (
  649. WPARAM wParam,
  650. LPARAM lParam
  651. )
  652. {
  653. for (int index = 0; index < APP_MAX; index ++) {
  654. const APP_INFO &app_info = APPLICATIONS[index];
  655. if (LOWORD (wParam) == app_info.ctrl_id) {
  656. //
  657. // Enable or disable the clean and directory buttons
  658. //
  659. bool enable = (SendDlgItemMessage (LOWORD(wParam), BM_GETCHECK) == 1);
  660. ::EnableWindow (::GetDlgItem (m_hWnd, app_info.clean_ctrl_id), enable);
  661. ::EnableWindow (::GetDlgItem (m_hWnd, app_info.dir_ctrl_id), enable);
  662. } else if (LOWORD (wParam) == app_info.dir_ctrl_id) {
  663. //
  664. // Change the installation directoy
  665. //
  666. CString directory;
  667. CString dlg_title;
  668. dlg_title.Format ("Select a directory to install the %s to.", app_info.title);
  669. if (Get_Install_Directory (m_hWnd, dlg_title, directory)) {
  670. SetDlgItemText (app_info.dir_ctrl_id, directory);
  671. }
  672. }
  673. }
  674. return CDialog::OnCommand(wParam, lParam);
  675. }
  676. //////////////////////////////////////////////////////////////////////////////////
  677. //
  678. // OnDefaults
  679. //
  680. //////////////////////////////////////////////////////////////////////////////////
  681. void
  682. CW3DUpdateDlg::OnDefaults (void)
  683. {
  684. for (int index = 0; index < APP_MAX; index ++) {
  685. const APP_INFO &app_info = APPLICATIONS[index];
  686. if (SendDlgItemMessage (app_info.ctrl_id, BM_GETCHECK) != 0) {
  687. SetDlgItemText (app_info.dir_ctrl_id, app_info.default_dir);
  688. }
  689. }
  690. return ;
  691. }
  692. void CW3DUpdateDlg::RegisterShellExt()
  693. {
  694. HKEY reg_key;
  695. CString reg_key_name(MAKEINTRESOURCE(IDS_SHELLEXT_CLSID));
  696. CString reg_value(MAKEINTRESOURCE(IDS_SHELLEXT_NAME));
  697. CString value_name;
  698. //[HKEY_CLASSES_ROOT\CLSID\{556F8779-49C4-4e88-9CEF-0AC2CFD6B763}]
  699. DWORD ret_val = ::RegCreateKeyEx (HKEY_CLASSES_ROOT,reg_key_name,0L,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&reg_key,NULL);
  700. if (ERROR_SUCCESS == ret_val) {
  701. // @="W3D Shell Extension"
  702. ret_val = ::RegSetValueEx(reg_key,"",0L,REG_SZ,(BYTE *)(LPCTSTR)reg_value,reg_value.GetLength () + 1);
  703. }
  704. //[HKEY_CLASSES_ROOT\CLSID\{556F8779-49C4-4e88-9CEF-0AC2CFD6B763}\InProcServer32]
  705. ::RegCloseKey (reg_key);
  706. reg_key_name += "\\InProcServer32";
  707. ret_val = ::RegCreateKeyEx (HKEY_CLASSES_ROOT,reg_key_name,0L,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&reg_key,NULL);
  708. if (ERROR_SUCCESS == ret_val){
  709. //@="W3Dshellext.dll"
  710. reg_value.LoadString(IDS_SHELLEXT_DLLNAME);
  711. ret_val = ::RegSetValueEx(reg_key, "",0L,REG_SZ,(BYTE *)(LPCTSTR)reg_value,reg_value.GetLength () + 1);
  712. //"ThreadingModel"="Apartment"
  713. reg_value.LoadString(IDS_W3DSHELLEXT_APARTMENT);
  714. value_name.LoadString(IDS_W3DSHELLEXT_THMODEL);
  715. ret_val = ::RegSetValueEx(reg_key, value_name,0L,REG_SZ,(BYTE *)(LPCTSTR)reg_value,reg_value.GetLength () + 1);
  716. }
  717. ::RegCloseKey (reg_key);
  718. //[HKEY_CLASSES_ROOT\.w3d]
  719. reg_key_name.LoadString(IDS_W3DFILEEXT);
  720. ret_val = ::RegCreateKeyEx (HKEY_CLASSES_ROOT,reg_key_name,0L,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&reg_key,NULL);
  721. if (ERROR_SUCCESS == ret_val) {
  722. //@="W3DFile"
  723. reg_value.LoadString(IDS_W3DFILETEXT);
  724. ret_val = ::RegSetValueEx(reg_key, "",0L,REG_SZ,(BYTE *)(LPCTSTR)reg_value,reg_value.GetLength () + 1);
  725. }
  726. ::RegCloseKey (reg_key);
  727. //[HKEY_CLASSES_ROOT\W3DFile]
  728. reg_key_name.LoadString(IDS_W3DFILEKEY);
  729. ret_val = ::RegCreateKeyEx (HKEY_CLASSES_ROOT,reg_key_name,0L,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&reg_key,NULL);
  730. if (ERROR_SUCCESS == ret_val) {
  731. //@="Shell Extension file"
  732. reg_value.LoadString(IDS_W3DSHELLEXT_TEXT);
  733. ret_val = ::RegSetValueEx(reg_key, "",0L,REG_SZ,(BYTE *)(LPCTSTR)reg_value,reg_value.GetLength () + 1);
  734. }
  735. ::RegCloseKey (reg_key);
  736. //[HKEY_CLASSES_ROOT\W3DFile\shellex\ContextMenuHandlers]
  737. reg_key_name.LoadString(IDS_CTXMENUHANDLERS);
  738. ret_val = ::RegCreateKeyEx (HKEY_CLASSES_ROOT,reg_key_name,0L,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&reg_key,NULL);
  739. if (ERROR_SUCCESS == ret_val) {
  740. //@="W3DCtxMenu"
  741. reg_value.LoadString(IDS_W3DMENU_TEXT);
  742. ret_val = ::RegSetValueEx(reg_key, "",0L,REG_SZ,(BYTE *)(LPCTSTR)reg_value,reg_value.GetLength () + 1);
  743. }
  744. ::RegCloseKey (reg_key);
  745. //[HKEY_CLASSES_ROOT\W3DFile\shellex\ContextMenuHandlers\W3DCtxMenu]
  746. reg_key_name.LoadString(IDS_W3DCTXMENU_KEY);
  747. ret_val = ::RegCreateKeyEx (HKEY_CLASSES_ROOT,reg_key_name,0L,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&reg_key,NULL);
  748. if (ERROR_SUCCESS == ret_val) {
  749. //@="{556F8779-49C4-4e88-9CEF-0AC2CFD6B763}"
  750. reg_value.LoadString(IDS_W3DSHELLEXT_GUID);
  751. ret_val = ::RegSetValueEx(reg_key, "",0L,REG_SZ,(BYTE *)(LPCTSTR)reg_value,reg_value.GetLength () + 1);
  752. }
  753. ::RegCloseKey (reg_key);
  754. //[HKEY_CLASSES_ROOT\W3DFile\shellex\PropertySheetHandlers]
  755. reg_key_name.LoadString(IDS_W3DPROPSHEETHANDLERS);
  756. ret_val = ::RegCreateKeyEx (HKEY_CLASSES_ROOT,reg_key_name,0L,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&reg_key,NULL);
  757. if (ERROR_SUCCESS == ret_val) {
  758. //@="W3DPropertyPage"
  759. reg_value.LoadString(IDS_W3DPROPPAGE_TEXT);
  760. ret_val = ::RegSetValueEx(reg_key, "",0L,REG_SZ,(BYTE *)(LPCTSTR)reg_value,reg_value.GetLength () + 1);
  761. }
  762. ::RegCloseKey (reg_key);
  763. //[HKEY_CLASSES_ROOT\W3DFile\shellex\PropertySheetHandlers\W3DPropertyPage]
  764. reg_key_name.LoadString(IDS_W3DPROPPAGE_KEY);
  765. ret_val = ::RegCreateKeyEx (HKEY_CLASSES_ROOT,reg_key_name,0L,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&reg_key,NULL);
  766. if (ERROR_SUCCESS == ret_val) {
  767. //@="{556F8779-49C4-4e88-9CEF-0AC2CFD6B763}"
  768. reg_value.LoadString(IDS_W3DSHELLEXT_GUID);
  769. ret_val = ::RegSetValueEx(reg_key, "",0L,REG_SZ,(BYTE *)(LPCTSTR)reg_value,reg_value.GetLength () + 1);
  770. }
  771. ::RegCloseKey (reg_key);
  772. //[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved]
  773. reg_key_name.LoadString(IDS_MSEXTENSIONS_KEY);
  774. ret_val = ::RegCreateKeyEx (HKEY_LOCAL_MACHINE,reg_key_name,0L,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&reg_key,NULL);
  775. if (ERROR_SUCCESS == ret_val) {
  776. //"{556F8779-49C4-4e88-9CEF-0AC2CFD6B763}"="W3D Shell Extension"
  777. value_name.LoadString(IDS_W3DSHELLEXT_GUID);
  778. reg_value.LoadString(IDS_W3DSHELLEXT_TEXT);
  779. ret_val = ::RegSetValueEx(reg_key, value_name,0L,REG_SZ,(BYTE *)(LPCTSTR)reg_value,reg_value.GetLength () + 1);
  780. }
  781. ::RegCloseKey (reg_key);
  782. //[HKEY_CLASSES_ROOT\W3DFile\\DefaultIcon
  783. reg_key_name.LoadString(IDS_W3DDEFAULTICON_KEY);
  784. ret_val = ::RegCreateKeyEx (HKEY_CLASSES_ROOT,reg_key_name,0L,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&reg_key,NULL);
  785. if (ERROR_SUCCESS == ret_val) {
  786. //%SystemRoot%\\system32\\W3DShellExt.dll,0
  787. reg_value.LoadString(IDS_W3DDEFAULTICON_TEXT);
  788. ret_val = ::RegSetValueEx(reg_key, "",0L,REG_SZ,(BYTE *)(LPCTSTR)reg_value,reg_value.GetLength () + 1);
  789. }
  790. SHChangeNotify(SHCNE_ASSOCCHANGED,SHCNF_IDLIST ,NULL,NULL);
  791. }
  792. void CW3DUpdateDlg::RegisterViewer(int index){
  793. HKEY reg_key;
  794. CString reg_key_name(MAKEINTRESOURCE(IDS_OPENWITH));
  795. CString dest_path;
  796. Get_Destination_Path(index, dest_path);
  797. CString reg_value(MAKEINTRESOURCE(IDS_VIEWERCOMMAND));
  798. reg_value = dest_path + reg_value;
  799. //[HKEY_CLASSES_ROOT\CLSID\{556F8779-49C4-4e88-9CEF-0AC2CFD6B763}]
  800. DWORD ret_val = ::RegCreateKeyEx (HKEY_CLASSES_ROOT,reg_key_name,0L,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&reg_key,NULL);
  801. if (ERROR_SUCCESS == ret_val) {
  802. // @="W3D Shell Extension"
  803. ret_val = ::RegSetValueEx(reg_key,"",0L,REG_SZ,(BYTE *)(LPCTSTR)reg_value,reg_value.GetLength () + 1);
  804. }
  805. }