source: trunk/gsinstaller/gsinstall.cpp@ 1502

Last change on this file since 1502 was 1502, checked in by cs025, 24 years ago

Properly creates and destroys the gssetup.exe executable

  • Property svn:keywords set to Author Date Id Revision
File size: 31.6 KB
Line 
1#include <vector>
2#include <string>
3using namespace std;
4
5#include <stdlib.h>
6#include <stdio.h>
7#include <windows.h>
8#include <commctrl.h>
9
10#include "dirSelector.h"
11#include "common.h"
12#include "configFile.h"
13#include "File.h"
14#include "FilePath.h"
15#include "FileCopier.h"
16#include "launchApp.h"
17#include "unInstall.h"
18
19#include "gsRegistry.h"
20#include "gsPlatform.h"
21#include "gsProgman.h"
22#include "gsProfile.h"
23#include "gsManifest.h"
24
25char * app_cmdLine;
26static char app_name[] = "Greenstone Installer";
27HINSTANCE app_instance;
28HWND app_window;
29
30bool config_complete = false;
31
32typedef vector<dirSelector *> dirSelVector;
33
34class GSInstall : public installManager
35{ private:
36 configureFile * configFile; // the installation configure file
37
38 FilePath * collectPath; // where the collection is currently installed
39 FilePath * installToPath; // the first cut at a destination folder
40 FilePath * sourcePath; // the root source folder
41 FilePath * gsdlSourcePath; // the gsdl folder in the source area
42 FilePath * destinationPath; // where the executables will be installed to
43 FilePath * dataDestPath; // where the collection data files will go
44
45 bool installVolume; // whether to install collection data
46 bool installFullVolume;// whether to install all collection data
47
48 dirSelVector selectedDirs; // configuration objects
49
50 gsPlatform platform; // platform information
51 gsRegistry * gsRegister; // registry
52 gsManifest * manifest; // manifest of files
53 gsProgramManager * progman; // program manager connection
54
55 void getSourcePath();
56 void getExistingInstall();
57 public:
58 bool installExe;
59
60 GSInstall(bool uninstall);
61 FilePath * collectionPath();
62 FilePath * installPath();
63 bool copyFiles();
64 bool updateRegistry();
65 bool updateProfiles();
66 bool updateProgman();
67 bool updateSetupExe();
68 bool installNetscape();
69 void setDestination();
70 bool setUninstall();
71 void uninstall();
72 void setManifest();
73 void addSelectedDir(dirSelector *selector);
74};
75
76static string gsdl_DBHOME = "gdbmhome";
77static string gsdl_VLHOME = "gsdlhome";
78static string gsdl_STATIC = "staticpath";
79static string gsdl_COLLIST= "collections";
80
81void gsInstall_getDesktopExt(int *sx, int *sy)
82{
83 HDC dc = GetDC(GetDesktopWindow());
84 *sx = GetDeviceCaps(dc, HORZRES);
85 *sy = GetDeviceCaps(dc, VERTRES);
86 ReleaseDC(GetDesktopWindow(), dc);
87}
88
89/**
90 * Get various and nefarious details before we start trying an installation.
91 * The installation configuration file is read, we seek for an existing
92 * installation and reconfigure the default install settings appropriately.
93 * THe source path is also discovered.
94 */
95GSInstall::GSInstall(bool uninstall)
96 : installManager()
97{ // get the installation configuration file
98 this->configFile = new configureFile("install.cfg");
99
100 // set up "default" installation bits
101 this->installToPath = new FilePath("C:\\GSDL");
102 this->collectPath = NULL;
103 this->installExe = true; // we must install the exe files
104
105 // don't attempt this with windows 3.1
106 if (!this->platform.isWindows32s())
107 { // get the registry
108 this->gsRegister = new gsRegistry(*this, *this->configFile);
109 }
110 else
111 { // TODO: in windows 3.1 we can't use the register as it isn't fully/properly
112 // implemented; we must get the existing path information from elsewhere
113 this->gsRegister = new gsRegistry(*this, *this->configFile);
114 }
115
116 // assume for now we will install the full volume and the database
117 this->installVolume = true;
118 this->installFullVolume = true;
119
120 // detect any existing installation; unnecessary in uninstall (it's the
121 // "source" directory - see later
122 if (uninstall == false)
123 { this->getExistingInstall();
124 }
125
126 // get where we are installing from
127 this->getSourcePath();
128
129 // if doing an uninstall we now know where the "uninstall" is
130 if (uninstall == true)
131 { this->collectPath = this->sourcePath;
132 }
133
134 // get the manifest and program manager objects
135 if (uninstall)
136 { this->manifest = new gsManifest(*this);
137 }
138 else
139 { this->manifest = new gsManifest(*this, *this->sourcePath);
140 }
141 this->progman = new gsProgramManager(*this);
142
143 // tell manifest the number of bits in the raw windows environment; this may
144 // be required for loading certain modules such as winsock; the number of
145 // macros is over-the-top, but is more robust to unforeseen future requirements
146/* if (platform.isWindows32s())
147 { this->manifest->expandMacro("WINBITS", "16");
148 this->manifest->expandMacro("WIN16", "16");
149 this->manifest->expandMacro("WIN32", "32");
150 }
151 else
152 { this->manifest->expandMacro("WINBITS", "32");
153 this->manifest->expandMacro("WIN16", "");
154 this->manifest->expandMacro("WIN32", "32");
155 }
156*/
157 // inform manifest of collection directory name
158 string colDir;
159 colDir = this->configFile->getString("CollectionDirName");
160 if (colDir != "")
161 { this->manifest->expandMacro("COLDIRNAME", colDir);
162 }
163}
164
165/**
166 * Detect the presence of an existing installation
167 */
168void GSInstall::getExistingInstall()
169{ if (!this->platform.isWindows32s())
170 { if (gsRegister->collectionInstalled())
171 { // TODO: check if receptionist etc should be replaced or not
172
173 // TODO: check build version of the volume
174
175 // Get location of the library executable from the registry; this
176 // is thence used to get the location of gsdl.ini etc.
177 this->collectPath = this->gsRegister->collectionPath();
178 if (this->collectPath != "")
179 { this->installToPath = this->collectPath;
180
181 // we don't need to install the exe files
182 this->installExe = false;
183 }
184 }
185 }
186}
187
188/**
189 * get the source path for this install; we derive this from the path of this
190 * executable (the installer)
191 */
192void GSInstall::getSourcePath()
193{ static char filename[512];
194 FilePath *exePath;
195
196 // get the filepath of this executable
197 GetModuleFileName(0, filename, 512);
198 exePath = new FilePath(filename);
199
200 // get the parent (i.e. the folder containing this executable) for the source
201 // folder
202 this->sourcePath = exePath->parent();
203
204 // get the gsdl source path
205 this->gsdlSourcePath = new FilePath(this->sourcePath->pathString(), "gsdl");
206 delete exePath;
207}
208
209/**
210 * Controls the actual copying of the files; manifests of what to install
211 * are read in from a configuration on the hard drive - this should be basically
212 * greenstone dependent, and void of any collection-specific rubbish!
213 */
214bool GSInstall::copyFiles()
215{ // ensure that we have got the required destination and that we can write there
216 if (this->installExe)
217 { this->destinationPath->ensureWriteablePath();
218 }
219
220 // ensure that the destination path for the collection itself is available
221 if (this->installVolume)
222 { this->dataDestPath->ensureWriteablePath();
223 }
224
225 // do the copy
226 this->manifest->copy(this->gsdlSourcePath);
227
228 return true;
229}
230
231/**
232 * Fulfill registry update requirements; first the keys are set up, then they
233 * are filled with key item/value pairs.
234 */
235bool GSInstall::updateRegistry()
236{ // don't do registry stuff under windows 32s
237 if (this->platform.isWindows32s() && FALSE)
238 { return true;
239 }
240
241 // ensure all pertinent keys already exist for this volume/collection
242 this->gsRegister->ensureKeysExist();
243
244 // now move on to add key items
245 if (this->installExe)
246 { FilePath *serverPath = new FilePath(this->destinationPath->pathString(), "server.exe");
247 FilePath *setupPath = new FilePath(this->destinationPath->pathString(), "gssetup.exe");
248 FilePath *logPath = new FilePath(this->destinationPath->pathString(), "install.log");
249 string exeKeyPath, uninstallCmd, uninstallKeyPath;
250 gsPlatform platform;
251
252 // store the normal collection key information
253 this->gsRegister->storeKeyString( HKEY_LOCAL_MACHINE,
254 this->gsRegister->collectKeyId(),
255 "library",
256 serverPath->pathString());
257
258 // This test is in fact for 9x or NT 4+; we're worried about the registry
259 // format, not about the shell as such
260 if (platform.isExplorerShell())
261 { // get special app path key for windows 9x
262 exeKeyPath = this->gsRegister->exeKeyId("library.exe");
263
264 // ensure that the exe key exists
265 this->gsRegister->ensureKeyExists(HKEY_LOCAL_MACHINE, exeKeyPath);
266
267 // store default key for this application
268 this->gsRegister->storeKeyString( HKEY_LOCAL_MACHINE,
269 exeKeyPath,
270 "",
271 serverPath->pathString());
272
273 // store path for this application
274 this->gsRegister->storeKeyString( HKEY_LOCAL_MACHINE,
275 exeKeyPath,
276 "path",
277 this->destinationPath->pathString());
278
279 // create uninstall command line
280 uninstallCmd = setupPath->pathString() + " -u " + logPath->pathString();
281 uninstallKeyPath = this->gsRegister->uninstallKeyId(this->configFile->getString("CollectionName"));
282
283 // ensure uninstall key exists
284 this->gsRegister->ensureKeyExists(HKEY_LOCAL_MACHINE, uninstallKeyPath);
285
286 this->gsRegister->storeKeyString(HKEY_LOCAL_MACHINE, uninstallKeyPath,
287 "DisplayName",
288 this->configFile->getString("CollectionName"));
289 this->gsRegister->storeKeyString(HKEY_LOCAL_MACHINE, uninstallKeyPath,
290 "UninstallString", uninstallCmd);
291 }
292 delete setupPath;
293 delete serverPath;
294 delete logPath;
295 }
296
297 if (this->installVolume || this->installFullVolume)
298 { // no actual key items are held in the volume key; for future use
299 }
300 return true;
301}
302
303/**
304 * Set the destination directory details
305 */
306void GSInstall::setDestination()
307{ // get configuration from the install wizard pages
308 this->destinationPath = new FilePath(this->selectedDirs[0]->selectedPath());
309 this->installFullVolume = this->selectedDirs[1]->getOption();
310 if (this->installFullVolume || true) // NB: always take path from 2nd dialog
311 { this->dataDestPath = new FilePath(this->selectedDirs[1]->selectedPath());
312 }
313 else
314 { this->dataDestPath = this->destinationPath;
315 }
316
317 // open the log for writing
318 FilePath *logPath = new FilePath(this->destinationPath->pathString(), "install.log");
319 this->openLog(logPath->pathString(), true);
320 delete logPath;
321}
322
323bool GSInstall::setUninstall()
324{ char tempPathStr[MAX_PATH];
325
326 // if we failed to get the Windows temporary directory, abort
327 if (GetTempPath(MAX_PATH, tempPathStr) == 0)
328 { // TODO: abort!
329 return false;
330 }
331
332 FilePath tempPath(tempPathStr);
333
334 // if we are not running in the Windows temporary directory, copy this exe
335 // and the installation log to the temporary directory and run them there
336 if (*this->sourcePath != tempPath)
337 { // copy this and install.log to temporary directory and restart
338 FilePath exePath(*this->sourcePath, "gssetup.exe");
339 FilePath logPath(*this->sourcePath, "install.log");
340
341 FilePath exeDest(tempPath, "gssetup.exe");
342 FilePath logDest(tempPath, "install.log");
343
344 CopyFile(exePath.cString(), exeDest.cString(), false);
345 CopyFile(logPath.cString(), logDest.cString(), false);
346
347 // now run the gssetup in the temporary directory
348 launchApp launchUninstall(exeDest);
349 launchUninstall.setCommandLine(" -u " + logPath.pathString());
350 launchUninstall.run(false, 0, "", "", false);
351
352 return false;
353 }
354
355 // open the log for reading from the directory this exe is now in (which
356 // will in fact be the temporary directory as outlined above)
357 FilePath *logPath = new FilePath(this->sourcePath->pathString(), "install.log");
358 this->openLog(logPath->pathString(), false);
359 delete logPath;
360
361 return true;
362}
363
364void GSInstall::uninstall()
365{ FilePath *iniPath;
366 string command;
367 stringArray params;
368
369 this->manifest = new gsManifest(*this); // get a manifest manager
370
371 iniPath = new FilePath(this->collectPath->pathString(), "gsdl.ini");
372 gsProfile gsdlProfile(*this, iniPath->pathString());
373
374 while ((command = this->popCommand(params)) != "")
375 { if (!this->manifest->undoAction(command, params))
376 { if (!gsdlProfile.undoAction(command, params))
377 { if (!this->gsRegister->undoAction(command, params))
378 { if (!this->progman->undoAction(command, params))
379 {
380 }
381 }
382 }
383 }
384 }
385}
386
387/**
388 * Collate the manifest for installation
389 */
390void GSInstall::setManifest()
391{ if (this->installExe)
392 { this->manifest->selectGroup("library", *this->destinationPath);
393 }
394 if (this->installFullVolume)
395 { this->manifest->selectGroup("collection", *this->dataDestPath);
396 }
397 else
398 { this->manifest->selectGroup("database", *this->dataDestPath);
399 }
400}
401
402/**
403 * Update the program manager/explorer shell with icons, groups etc for this
404 * collection/application
405 */
406bool GSInstall::updateProgman()
407{ string groupName;
408
409 // if we managed to get a connection to the program manager (or explorer
410 // shell) then do the requisite updates
411 if (this->progman->connect())
412 { // get group name from folders
413 groupName = this->configFile->getString("ProgramGroupName");
414 if (groupName == "")
415 { // TODO: error handling
416 this->progman->disconnect();
417 return false;
418 }
419
420 // add the group
421 if (!this->progman->addProgramGroup(groupName))
422 { this->progman->disconnect();
423 return false;
424 }
425
426 // add a "server" icon
427 FilePath libraryPath(this->destinationPath->pathString(), "library.exe");
428 if (!this->progman->addIcon(groupName, "Library (without nextwork support)", libraryPath.pathString(), ""))
429 { // assume that it may be there already
430 }
431
432 // check for server existence
433 FilePath serverPath(this->destinationPath->pathString(), "server.exe");
434 if (serverPath.exists())
435 { if (!this->progman->addIcon(groupName, "Server", serverPath.pathString(), ""))
436 { // assume that it may be there already
437 }
438 }
439
440 FilePath readMePath(this->destinationPath->pathString(), "readme.txt");
441 if (!this->progman->addIcon(groupName, "ReadMe", readMePath.pathString(), ""))
442 {
443 }
444
445 FilePath supportPath(this->destinationPath->pathString(), "support.html");
446 if (!this->progman->addIcon(groupName, "Technical Support", supportPath.pathString(), ""))
447 {
448 }
449
450 // TODO: uninstall icon
451 // FilePath uninstallPath(this->destinationPath->pathString(), "gssetup.exe");
452
453 // disconnect from program manager
454 this->progman->disconnect();
455 }
456 return true;
457}
458
459/**
460 * Update the profile (ini) files associated with the program; these changes
461 * must be made after copying to files in the destination/executable folders
462 * as we can't write to CD-ROM (or at least we shouldn't - the install would
463 * become tainted).
464 */
465bool GSInstall::updateProfiles()
466{ FilePath *exePath;
467 FilePath *dataPath;
468 FilePath *iniPath;
469
470 // if we're installing the exe, then the exe path leads to the destination
471 // folder of this installation sequence; if not, then we pick it up from
472 // the existing location of that folder
473 if (this->installExe)
474 { exePath = this->destinationPath;
475 }
476 else
477 { exePath = this->collectPath;
478 }
479 iniPath = new FilePath(exePath->pathString(), "gsdl.ini");
480
481 // TODO: check if this 'if' structure is correct; suspect that it isn't quite
482 // as we may not be installing the volume, but exe etc individually;
483 // may be okay now but not future proof; also the destination directory
484 // may or may not be tied to the exe directory if that existed already.
485 // This all needs investigating
486 if (this->installVolume)
487 { // Manufacture the appropriate section name now; an equivalent string
488 // is also constructed
489 string volumeSectionString = this->configFile->getString("CollectionName") +
490 "#" + this->configFile->getString("CollectionVolume");
491
492 // if we're installing the full data for the collection, then take the
493 // data path to be at the selected destination directory for the collection
494 // files; otherwise take the data path to be on the CD/distribution media
495 if (this->installFullVolume)
496 { dataPath = this->dataDestPath;
497 }
498 else
499 { dataPath = this->gsdlSourcePath;
500 }
501
502 // create a profile object to write to the gsdl.ini file
503 gsProfile gsdlProfile(*this, iniPath->pathString());
504
505 // if installing the executable, add the database and greenstone home
506 // directories
507 if (this->installExe)
508 { // set the correct exe entries in gsdl.ini (in the gsdl section)
509 gsdlProfile.writeString("gsdl", "gsdlhome", dataPath->pathString());
510 gsdlProfile.writeString("gsdl", "gdbmhome", this->dataDestPath->pathString());
511 }
512
513 // set the correct collection volume entries in gsdl.ini
514 if (this->installVolume)
515 { // note the collection in the general gsdl section; and add the undo item too
516 gsdlProfile.ensureListMember("gsdl", gsdl_COLLIST, volumeSectionString);
517
518 // note the volume data in its own section
519 gsdlProfile.writeString(volumeSectionString, "gsdlhome", dataPath->pathString());
520 gsdlProfile.writeString(volumeSectionString, "gdbmhome", this->dataDestPath->pathString());
521 gsdlProfile.writeString(volumeSectionString, "staticpath", dataPath->pathString());
522 }
523 }
524
525 // clean up
526 delete iniPath;
527
528 return true;
529}
530
531/**
532 * Ensure that we've installed the very latest setup executable @ the destination/
533 * greenstone folder
534 */
535bool GSInstall::updateSetupExe()
536{ FilePath *destExePath;
537 FilePath srcExeFile(*this->sourcePath, "gssetup.exe");
538
539 if (this->installExe)
540 { destExePath = this->destinationPath;
541 }
542 else
543 { destExePath = this->collectPath;
544 }
545 FilePath destExeFile(*destExePath, "gssetup.exe");
546
547 if (!CopyFile(srcExeFile.cString(), destExeFile.cString(), false))
548 { return false;
549 }
550 return true;
551}
552
553bool GSInstall::installNetscape()
554{ FilePath netscape32Path(this->sourcePath->pathString(), "netscape\\n32e405.exe");
555 FilePath netscape16Path(this->sourcePath->pathString(), "netscape\\n16e405.exe");
556
557 launchApp launchNetscape(netscape32Path);
558 launchNetscape.platformApp(gsPlatform_WINDOWS32S, netscape16Path);
559 if (launchNetscape.run(true, 1,
560 "This library is displayed using a web browser. If you don't "
561 "currently have a web browser installed on your machine you may "
562 "install the Netscape 4.05 browser now.\n\n"
563 "Note that if your current browser was provided by your internet "
564 "service provider, you should install Netscape in a different "
565 "directory.\n\n"
566 "Would you like to install the Netscape 4.05 browser now?",
567 "Greenstone Installer", false) < 0)
568 { MessageBox(0, "Error", app_name, MB_OK);
569 return false;
570 }
571 return true;
572}
573
574FilePath *GSInstall::collectionPath()
575{ return this->collectPath;
576}
577
578FilePath *GSInstall::installPath()
579{ return this->installToPath;
580}
581
582void GSInstall::addSelectedDir(dirSelector *selector)
583{ this->selectedDirs.push_back(selector);
584}
585
586typedef struct
587{ dirSelector * dirSelect;
588} GSInstall_dirPathData;
589
590HGLOBAL loadDirBrowser()
591{ HRSRC resHdl;
592
593 resHdl = FindResource(app_instance, "MySaveAsDlg", RT_DIALOG);
594 return LoadResource(app_instance, resHdl);
595}
596
597void gsInstall_wizard_centre(HWND dialog)
598{
599 RECT rect;
600 int sx, sy;
601 int dx, dy;
602
603 gsInstall_getDesktopExt(&sx, &sy);
604 GetWindowRect(dialog, &rect);
605
606 dx = (sx - rect.right + rect.left) >> 1;
607 dy = (sy - rect.bottom + rect.top) >> 1;
608 SetWindowPos(dialog, 0, dx, dy, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
609}
610
611BOOL FAR PASCAL GSInstall_dlgproc(HWND Dialog, UINT Message, WPARAM wParam, LPARAM lParam)
612{ static bool first = true; // static variable to hack the position of the
613 // whole wizard; note doing this in the wizard
614 // property sheet initialisation DOES NOT WORK
615
616 switch (Message)
617 { case WM_INITDIALOG:
618 { dirSelector *selector = (dirSelector *) ((PROPSHEETPAGE *) lParam)->lParam;
619
620 SetDlgItemText(Dialog, dirpath_PROMPT, selector->prompt);
621 if (selector->optPrompt != NULL)
622 { SetDlgItemText(Dialog, dirpath_OPTION, selector->optPrompt);
623 EnableWindow(GetDlgItem(Dialog, dirpath_BROWSE), true); // was false
624 EnableWindow(GetDlgItem(Dialog, dirpath_PATH), true); // was false
625 }
626 else
627 { ShowWindow(GetDlgItem(Dialog, dirpath_OPTION), SW_HIDE);
628 }
629 SetWindowLong(Dialog, GWL_USERDATA, ((PROPSHEETPAGE *) lParam)->lParam);
630 SetDlgItemText(Dialog, dirpath_PATH, selector->selectedPath());
631
632 // if this is the first time this function is called, then centre the
633 // wizard into the centre of our screen.
634 if (first)
635 { gsInstall_wizard_centre(GetParent(Dialog));
636 first = false;
637 }
638 }
639 return TRUE;
640
641 case WM_COMMAND:
642 switch (LOWORD(wParam))
643 { case dirpath_BROWSE:
644 ((dirSelector *) GetWindowLong(Dialog, GWL_USERDATA))->requestPath(Dialog, "Select Directory");
645 SetDlgItemText(Dialog, dirpath_PATH, ((dirSelector *) GetWindowLong(Dialog, GWL_USERDATA))->selectedPath());
646 break;
647
648 case dirpath_OPTION:
649 ((dirSelector *) GetWindowLong(Dialog, GWL_USERDATA))->setOption(IsDlgButtonChecked(Dialog, dirpath_OPTION));
650 if (HIWORD(wParam) == BN_CLICKED && false) // don't do the enable/disable these days
651 { EnableWindow(GetDlgItem(Dialog, dirpath_BROWSE), IsDlgButtonChecked(Dialog, dirpath_OPTION));
652 EnableWindow(GetDlgItem(Dialog, dirpath_PATH), IsDlgButtonChecked(Dialog, dirpath_OPTION));
653 }
654 break;
655 }
656 break;
657
658 case WM_NOTIFY:
659 switch (((LPNMHDR) lParam)->code)
660 { case PSN_SETACTIVE:
661 { dirSelector *selector = ((dirSelector *) GetWindowLong(Dialog, GWL_USERDATA));
662 if (selector->isFinal())
663 { PropSheet_SetWizButtons(GetParent(Dialog), PSWIZB_BACK | PSWIZB_FINISH);
664 }
665 else
666 { PropSheet_SetWizButtons(GetParent(Dialog), PSWIZB_BACK | PSWIZB_NEXT);
667 }
668 }
669 break;
670
671 case PSN_KILLACTIVE:
672 break;
673
674 case PSN_WIZNEXT:
675 { // note the path from the dialog
676 dirSelector *selector = ((dirSelector *) GetWindowLong(Dialog, GWL_USERDATA));
677 selector->setPathFromEdit(GetDlgItem(Dialog, dirpath_PATH));
678
679 // create a new FilePath object to check on the proposed destination
680 FilePath *path = new FilePath(selector->selectedPath());
681
682 // if the proposed destination doesn't exist, ask the user whether to
683 // create it now. TODO: actually create it if asked!
684 if (path->exists() == false)
685 { char buffer[128];
686
687 sprintf(buffer, "Directory %s does not exist - create it?", selector->selectedPath());
688
689 // if the user cancelled that, then don't permit them to go to the next
690 // page of the wizard
691 if (MessageBox(0, buffer, app_name, MB_YESNO | MB_TOPMOST) == IDNO)
692 { delete path;
693 SetWindowLong(Dialog, DWL_MSGRESULT, TRUE);
694 return TRUE;
695 }
696 }
697 delete path;
698 }
699 break;
700
701 case PSN_WIZFINISH:
702 { // Finish the activity now
703 config_complete = true;
704 }
705 break;
706 }
707 break;
708 }
709 return FALSE;
710}
711
712void GSInstall_init_propertySheet(PROPSHEETPAGE &ppage, char *prompt, char *optPrompt,
713 char *title, GSInstall &installer, bool isFinal)
714{ GSInstall_dirPathData *data = new GSInstall_dirPathData;
715
716 data->dirSelect = new dirSelector(prompt, optPrompt, title, installer.installPath());
717 data->dirSelect->setFinal(isFinal);
718
719 installer.addSelectedDir(data->dirSelect);
720
721 ppage.dwSize = sizeof(PROPSHEETPAGE);
722 ppage.dwFlags = PSP_USETITLE;
723 ppage.hInstance = app_instance;
724 ppage.pszTemplate = "getDirPath";
725 ppage.pszIcon = 0;
726 ppage.pszTitle = app_name;
727 ppage.pfnDlgProc = (DLGPROC) GSInstall_dlgproc;
728 ppage.lParam = (LPARAM) data->dirSelect;
729 ppage.pfnCallback = NULL;
730}
731
732int CALLBACK GSInstall_wizardProc(HWND dialog, UINT Message, LPARAM lParameter)
733{ switch (Message)
734 { case PSCB_INITIALIZED :
735 // Process PSCB_INITIALIZED
736 gsInstall_wizard_centre(dialog);
737 break ;
738
739 case PSCB_PRECREATE :
740 // Process PSCB_PRECREATE
741 break ;
742
743 default :
744 // Unknown message
745 break ;
746 }
747 return 0;
748}
749
750bool GSInstall_init_wizard(GSInstall &install)
751{ PROPSHEETHEADER pshead;
752 PROPSHEETPAGE ppage[2];
753 bool reply;
754
755 ZeroMemory(&pshead, sizeof(PROPSHEETHEADER));
756 pshead.dwSize = sizeof(PROPSHEETHEADER);
757 pshead.dwFlags = PSH_PROPSHEETPAGE | PSH_USECALLBACK | PSH_USEHICON | PSH_WIZARD;
758 pshead.hwndParent = app_window;
759 pshead.hInstance = app_instance;
760 pshead.hIcon = NULL;
761 pshead.pszCaption = "Greenstone Installer";
762 pshead.nPages = 2;
763 pshead.nStartPage = 0;
764 if (install.installExe == true)
765 { pshead.ppsp = ppage;
766 }
767 else // cheat as the executable etc. is already installed
768 { pshead.ppsp = &ppage[1];
769 }
770 pshead.pfnCallback = GSInstall_wizardProc;
771
772 GSInstall_init_propertySheet( ppage[0],
773 "Choose a directory to install your "
774 "GreenStone software to.", NULL,
775 "Select", install, false);
776 GSInstall_init_propertySheet(ppage[1],
777 "Choose a directory to install the collection "
778 "files to.\n\n"
779 "You can also choose to install all the collection "
780 "files onto your computer hard drive.\n\n"
781 "If you do this, you will not have to load the "
782 "CD-ROM each time you use your Greenstone software "
783 "but more of your hard disk will be used.\n\n"
784 "Some collection files must be installed on your "
785 "computer.\n\n",
786 "Install all collection files",
787 "Select", install, true);
788
789 reply = (PropertySheet (&pshead) >= 0);
790 return reply;
791}
792
793long FAR PASCAL GSInstallWindProc(HWND Window,
794 WORD Message,
795 WPARAM wParameter,
796 LPARAM lParameter)
797{ long reply = 0;
798
799 switch(Message)
800 { case WM_CREATE:
801 { ShowWindow(Window, SW_MAXIMIZE);
802 }
803 break;
804
805 case WM_COMMAND:
806 break;
807
808 case WM_USER:
809 { // uninstall action
810 if (strstr(app_cmdLine, "-u") != NULL)
811 { // skip past the -u option itself
812 char *at = strstr(app_cmdLine, "-u");
813 at += strlen("-u");
814
815 // extract the log file path from the command line
816 while (*at == ' ')
817 { at ++;
818 }
819 string logPathString(at);
820 FilePath logPath(logPathString);
821
822 GSInstall install(true);
823 // if we're running in the temporary directory, do the uninstall
824 if (install.setUninstall())
825 { install.uninstall();
826
827 // close the log to write back all changes to the log; if the file
828 // will be deleted, it must be closed; copying may also fail, so it's
829 // safer to close it before doing either.
830 install.closeLog();
831
832 // if the install is empty, terminate all final items (currently the
833 // log and setup executables,
834 if (install.isEmpty())
835 { // delete the log file
836 DeleteFile(logPath.cString());
837
838 // get it's parent to find where the gssetup executable will be
839 FilePath *logParent = logPath.parent();
840 FilePath uninstallPath(*logParent, "gssetup.exe");
841
842 // delete the gssetup executable
843 DeleteFile(uninstallPath.cString());
844
845 // dispose of the parent directory information
846 delete logParent;
847 }
848 // if not, then overwrite the original log with the modified one
849 else
850 { // do nothing - should be changed already!
851 }
852 }
853 }
854 // install wizard
855 else
856 { GSInstall install(false);
857 GSInstall_init_wizard(install);
858 if (config_complete == false)
859 { MessageBox(0, "Install cancelled", app_name, MB_OK);
860 }
861 else
862 { // configure the installation
863 install.setDestination();
864 install.setManifest();
865
866 // perform installation
867 install.copyFiles();
868 install.updateProgman();
869 install.updateRegistry();
870 install.updateProfiles();
871 install.updateSetupExe();
872
873 // the log will need reopening (probably failed initially)
874 install.reopenLog();
875
876 // close log
877 install.closeLog();
878
879 // do further actions
880 install.installNetscape();
881 }
882 }
883 DestroyWindow(Window);
884 }
885 break;
886
887 case WM_CLOSE:
888/* if (!file_ischanged || IDCANCEL != file_query(Window, file_name))*/
889 DestroyWindow(Window);
890 return 0L;
891
892 case WM_DESTROY:
893 { PostQuitMessage(0);
894 }
895 break;
896
897 default:
898 return(DefWindowProc(Window, Message, wParameter, lParameter));
899 }
900 return reply;
901}
902
903void GSInstall_init(HINSTANCE instance, int Show)
904{ int sx, sy;
905
906 gsInstall_getDesktopExt(&sx, &sy);
907
908 app_window = CreateWindow("GSInstall:Main", "GreenStone Installer",
909 WS_OVERLAPPEDWINDOW | WS_MAXIMIZE | CS_DBLCLKS,
910 0, 0,
911 sx, sy,
912 NULL,
913 NULL,
914 app_instance,
915 NULL);
916
917 ShowWindow(app_window, Show);
918
919 PostMessage(app_window, WM_USER, 0, 0L);
920}
921
922void WinClassInit(void)
923{ WNDCLASS Class;
924
925 Class.lpszClassName = "GSInstall:Main";
926 Class.hInstance = app_instance;
927 Class.lpfnWndProc = (WNDPROC) GSInstallWindProc;
928 Class.hCursor = LoadCursor(NULL, IDC_ARROW);
929 Class.hIcon = NULL; //LoadIcon(app_instance, "GSInstall");
930 Class.lpszMenuName = NULL;
931 Class.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE+1);
932 Class.style = NULL;
933 Class.cbClsExtra = 0;
934 Class.cbWndExtra = 0;
935 RegisterClass(&Class);
936/*
937 Class.lpszClassName = "GSInstall:Splash";
938 Class.hInstance = app_instance;
939 Class.lpfnWndProc = (WNDPROC) splash_windproc;
940 Class.hCursor = LoadCursor(NULL, IDC_ARROW);
941 Class.hIcon = NULL;
942 Class.lpszMenuName = NULL;
943 Class.hbrBackground = (HBRUSH) (COLOR_WINDOW+1);
944 Class.style = NULL;
945 Class.cbClsExtra = 0;
946 Class.cbWndExtra = 0;
947 RegisterClass(&Class);*/
948}
949
950int PASCAL WinMain(HINSTANCE Current,
951 HINSTANCE Previous,
952 LPSTR CmdLine,
953 int CmdShow)
954{ MSG msg;
955// HACCEL accel;
956
957 app_cmdLine = (char *) malloc(lstrlen(CmdLine) + 1);
958 lstrcpy(app_cmdLine, CmdLine);
959
960 app_instance = Current;
961 /* -- init application */
962 if (!Previous)
963 { WinClassInit();
964 InitCommonControls();
965// grbStatic_registerClass(Current);
966 }
967
968 /* -- init instance */
969 GSInstall_init(Current, CmdShow);
970
971// config_init("ReTreeval");
972
973// accel = LoadAccelerators(Current, "ReTreevalMenu");
974
975 while (GetMessage(&msg, NULL, 0, 0))
976 { /*if (!TranslateAccelerator(app_window, accel, &msg))
977 { */
978 TranslateMessage(&msg);
979 DispatchMessage(&msg);
980 /*}*/
981 }
982 return (int) msg.wParam;
983}
Note: See TracBrowser for help on using the repository browser.