source: trunk/gsinstaller/gsinstall.cpp@ 1498

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

Further changes for uninstaller

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