G:/ScriptBasic/source/sbsetup/setup.c

Go to the documentation of this file.
00001 /* 
00002 
00003 FILE:    setup.c
00004 DATE:    Aug 2002
00005 AUTHOR:  Peter Verhas
00006 LICENCE: GPL
00007 
00008 CONTENT:
00009  Install-Program for ScriptBasic
00010 
00011 This program was written using the setup code of yabasic
00012 at http://www.yabasic.de
00013 
00014 */
00015 
00016 #include <windows.h>
00017 #include <stdio.h>
00018 #include <stdlib.h>
00019 #include <shlobj.h>
00020 #include <shellapi.h>
00021 #include <commctrl.h>
00022 #include <ole2.h>
00023 #include <direct.h>
00024 #include <sys/stat.h>
00025 #include <process.h>
00026 
00027 #include <zlib.h>
00028 #include "../filesys.h"
00029 
00030 #include "resource.h"
00031 
00032 #define VERSION_TEXT "2.0.0"
00033 #define MAJOR 2
00034 #define MINOR 0
00035 #define BUILD 0
00036 
00037 // the number of KB free disk space needed to install ScriptBasic
00038 #define KBNEEDED 8000
00039 
00040 #define DEFAULT_PATH "C:\\ScriptBasic\\"
00041 /* headings for messageboxes */
00042 #define INSTALL_HEADING " Install ScriptBasic !"
00043 #define REMOVE_HEADING " Remove ScriptBasic !"
00044 #define SOFT              "SOFTWARE\\"
00045 
00046 /* shortcuts for registry */
00047 #define LOCAL             HKEY_LOCAL_MACHINE
00048 #define ROOT              HKEY_CLASSES_ROOT
00049 #define SOFT              "SOFTWARE\\"
00050 #define UNINSTALL         "SOFTWARE\\MICROSOFT\\WINDOWS\\CURRENTVERSION\\UNINSTALL\\"
00051 
00052 /* the compressed file that contains all the files to install */
00053 #define GZFILE            "sbcab.bin"
00054 
00055 /* operationmodes for My...() functions */
00056 #define INSTALL 1
00057 #define REMOVE  2
00058 
00059 /* defines for files() */
00060 #define RESET 1
00061 #define NEXT  2
00062 
00063 #define BASIC_NAME "ScriptBasic"
00064 #define BASIC_EXE "scriba.exe"
00065 #define BASIC_EXTENSION ".sb"
00066 #define BASIC_VERSION "2.0"
00067 #define BASIC_BUILD "0"
00068 #define BASIC_ICON "scriba.ico"
00069 #define BASDOC_ICON "scribadoc.ico"
00070 #define BASIC_README "readme.txt"
00071 #define BASIC_LICENSE "copying.txt"
00072 #define BASIC_SETUP "setup.exe"
00073 #define BASIC_LOG "scriba.log"
00074 
00075 #define DEFAULTFONT "swiss13"
00076 #define DEFAULTGEOMETRY "+10+10"
00077 
00078 /* shortcut for standard Message Box Style */
00079 #define MB_STYLE     MB_OK|MB_SYSTEMMODAL|MB_ICONINFORMATION
00080 
00081 // standard buffer length that should be enough
00082 #define SSLEN 1024
00083 int total_progress;      /* number of steps to advance progress counter */
00084 
00085 int GlobalSuccessFlag = 1;
00086 
00087 void progress(char *msg);
00088 
00089 char *pszInstallPath;
00090 HINSTANCE this_instance; /* instance */
00091 char *temppath;          /* path to store temporary files */
00092 char logs[10000];        /* string to compose log-message */
00093 int install;
00094 char *currentpath;       /* current path */
00095 int cancel;
00096 char string[SSLEN];
00097 char logfilename[SSLEN];
00098 int progress_wait;
00099 
00100 DWORD dwMajor,dwMinor,dwBuild;
00101 
00102 
00103 char *app(char *trail) /* append trail to pszInstallPath */
00104 {
00105   char *result;
00106   int i,t;
00107   
00108   i=(int)strlen(pszInstallPath);
00109   t=(int)strlen(trail);
00110   
00111   result=malloc(i+t+1);
00112   memcpy(result,pszInstallPath,i);
00113   memcpy(result+i,trail,t);
00114   result[t+i]='\0';
00115   
00116   return result;
00117 }
00118 
00119 
00120 int failReport(char *key,
00121                       char *action){
00122   char logs[SSLEN];
00123   int Q;
00124   void logit();
00125 
00126   sprintf(logs,"--Fail: SETUP was not able to %s the registry value \"%s\"\n",action,key);
00127   logit(logs);
00128   sprintf(logs,
00129 
00130 "SETUP was not able to %s the registry value\n\n%s\n\n"
00131 "Did you start SETUP.EXE with Administrator privilege?\n\n"
00132 "If you started SETUP.EXE as a normal user the installation\n"
00133 "will be partial, without modifying the system parameters.\n"
00134 "If you started setup as an administrator and you still see\n"
00135 "this message, then check that the registry key exists,\n"
00136 "and the user account you use to run setup has read and\n"
00137 "write access to it.\n"
00138 "\n"
00139 "Press \"Cancel\" if you want to stop the installation.\n"
00140 "Press \"Try Again\" after you modified security seetings to retry.\n"
00141 "Press \"Continue\" to ignore this error and skip this step.\n" 
00142              ,action,key);
00143   Q =
00144   MessageBoxEx(NULL,
00145                 logs,
00146                 "WARNING: Registry access error",
00147                 MB_CANCELTRYCONTINUE | MB_ICONWARNING,
00148                 0);
00149   if( Q == IDCANCEL ){
00150     sprintf(logs,"--Fail: Installation was aborted on user request.\n");
00151     return Q;
00152     }
00153   return Q;
00154   }
00155 
00156 /*POD
00157 =H Delete keys from the registry
00158 
00159 This function deletes keys from the registry
00160 
00161 Arguments:
00162 
00163 =itemize
00164 =item T<start> one of the predefined key (e.g. HKEY_CLASSES_ROOT)
00165 =item T<keyname> path to the key to delete
00166 =item T<subkey> subkey to delete 
00167 =noitemize
00168 /*FUNCTION*/
00169 static int DeleteRegistryKey(HKEY start,
00170                              char *keyname,
00171                              char *subkey
00172   ){
00173 /*noverbatim
00174 CUT*/
00175   HKEY key;
00176   
00177   char logs[SSLEN];
00178   int Q;
00179 
00180 RETRY:
00181   if (RegOpenKeyEx(start,keyname,0,KEY_ALL_ACCESS,&key)!=ERROR_SUCCESS) 
00182     goto FAIL_1;
00183   
00184   if(RegDeleteKey(key,subkey)!=ERROR_SUCCESS){
00185     RegCloseKey(key);
00186 FAIL_1:
00187     sprintf(logs, "%s\\%s\\%s",
00188                (start == LOCAL ? "HKEY_LOCAL_MACHINE" : "HKEY_CLASSES_ROOT"),keyname,subkey
00189            ); 
00190     Q = failReport(logs,"delete");
00191     if( Q == IDTRYAGAIN )goto RETRY;
00192     if( Q == IDCONTINUE ){
00193       GlobalSuccessFlag = 0;
00194       return TRUE;
00195       }
00196     return FALSE;
00197     }
00198   RegCloseKey(key);
00199   return TRUE;
00200 }
00201 
00202 /*POD
00203 =H Get string value from the ScriptBasic registry key
00204 
00205 This function gets a string value from the registry
00206 
00207 =verbatim
00208 HKEY_LOCAL_MACHINE\SOFTWARE\ScriptBasic\'name'
00209 =noverbatim
00210 
00211 If the value is non existent or is not a string then it returns T<NULL>.
00212 /*FUNCTION*/
00213 char *GetSBRegString(char *name
00214   ){
00215 /*noverbatim
00216 CUT*/
00217   static char *keyname="SOFTWARE\\ScriptBasic";
00218   HKEY  hkey;
00219   DWORD cbData,dwType;
00220   char  sData[SSLEN];
00221   char  xData[SSLEN];
00222 
00223   if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,keyname,0,KEY_READ,&hkey) != ERROR_SUCCESS) return NULL;
00224 
00225   cbData = SSLEN;
00226   *sData = (char)0;
00227   if (RegQueryValueEx(hkey,name,NULL,&dwType,sData,&cbData) != ERROR_SUCCESS) return NULL;
00228 
00229   if( dwType != REG_SZ && dwType != REG_EXPAND_SZ )return NULL;
00230 
00231   if( dwType == REG_EXPAND_SZ ){
00232     ExpandEnvironmentStrings(sData,xData,cbData);
00233     strcpy(sData,xData);
00234     dwType = REG_SZ;
00235     }
00236   RegCloseKey(hkey);
00237   return strdup(sData);
00238   }
00239 
00240 /*POD
00241 =H Get DWORD value from the ScriptBasic registry key
00242 
00243 This function gets a DWORD value from the registry
00244 
00245 =verbatim
00246 HKEY_LOCAL_MACHINE\SOFTWARE\ScriptBasic\'name'
00247 =noverbatim
00248 
00249 If the value is non existent or is not a DWORD then the function returns -1 otherwise
00250 it returns zero. The DWORD value is returned in the second argument.
00251 
00252 If error happens T<DW> is set to be zero. This also can be used to check error.
00253 /*FUNCTION*/
00254 DWORD GetSBRegDW(char *name,
00255                  DWORD *DW
00256   ){
00257 /*noverbatim
00258 CUT*/
00259   static char *keyname="SOFTWARE\\ScriptBasic";
00260   HKEY  hkey;
00261   DWORD cbData,dwType;
00262   DWORD dwDW;
00263 
00264   *DW = 0;
00265 
00266   if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,keyname,0,KEY_READ,&hkey) != ERROR_SUCCESS) return -1;
00267 
00268   cbData = sizeof(DWORD);
00269   if (RegQueryValueEx(hkey,name,NULL,&dwType,(LPBYTE)&dwDW,&cbData) != ERROR_SUCCESS) return -1;
00270 
00271   if( dwType != REG_DWORD )return -1;
00272   RegCloseKey(hkey);
00273 
00274   *DW = dwDW;
00275   return 0;
00276   }
00277 
00278 /*POD
00279 =H Put keys into registry
00280 
00281 put keys into Registry 
00282 
00283 Arguments:
00284 
00285 =itemize
00286 =item T<start>   : one of the predefined key (e.g. HKEY_CLASSES_ROOT)
00287 =item T<keyname> : path to the key to create
00288 =item T<name>    : subkey to create
00289 =item T<content> : it's content
00290 =noitemize
00291 /*FUNCTION*/
00292 int PutRegistryKey(HKEY start,
00293                    char *keyname,
00294                    char *name,
00295                    char *content
00296 ){
00297 /*noverbatim
00298 CUT*/
00299   HKEY key;
00300   DWORD status;
00301   char logs[SSLEN];
00302   int Q;
00303 
00304 RETRY:
00305   RegCreateKeyEx(start,keyname,0,"",
00306     0,KEY_ALL_ACCESS,NULL,&key,&status);
00307   if (RegSetValueEx(key,name,0,REG_SZ,
00308     content,(DWORD)strlen(content)+1)!=ERROR_SUCCESS) {
00309     sprintf(logs, "%s\\%s\\%s",
00310                (start == LOCAL ? "HKEY_LOCAL_MACHINE" : "HKEY_CLASSES_ROOT"),keyname,name
00311            ); 
00312     Q = failReport(logs,"write");
00313     if( Q == IDTRYAGAIN )goto RETRY;
00314     if( Q == IDCONTINUE ){
00315       GlobalSuccessFlag = 0;
00316       return TRUE;
00317       }
00318     return FALSE;
00319   }
00320   return TRUE;
00321 }
00322 
00323 /*POD
00324 =H Put expandable keys into registry
00325 
00326 put keys into Registry 
00327 
00328 Arguments:
00329 
00330 =itemize
00331 =item T<start>   : one of the predefined key (e.g. HKEY_CLASSES_ROOT)
00332 =item T<keyname> : path to the key to create
00333 =item T<name>    : subkey to create
00334 =item T<content> : it's content
00335 =noitemize
00336 /*FUNCTION*/
00337 int PutRegistryEKey(HKEY start,
00338                    char *keyname,
00339                    char *name,
00340                    char *content
00341 ){
00342 /*noverbatim
00343 
00344 This function puts the string into the registry as 
00345 CUT*/
00346   HKEY key;
00347   DWORD status;
00348   char logs[SSLEN];
00349   int Q;
00350 
00351 RETRY:
00352   RegCreateKeyEx(start,keyname,0,"",
00353     0,KEY_ALL_ACCESS,NULL,&key,&status);
00354   if (RegSetValueEx(key,name,0,REG_EXPAND_SZ,
00355     content,(DWORD)strlen(content)+1)!=ERROR_SUCCESS) {
00356     sprintf(logs, "%s\\%s\\%s",
00357                (start == LOCAL ? "HKEY_LOCAL_MACHINE" : "HKEY_CLASSES_ROOT"),keyname,name
00358            ); 
00359     Q = failReport(logs,"write");
00360     if( Q == IDTRYAGAIN )goto RETRY;
00361     if( Q == IDCONTINUE ){
00362       GlobalSuccessFlag = 0;
00363       return TRUE;
00364       }
00365     return FALSE;
00366   }
00367   return TRUE;
00368 }
00369 
00370 /*POD
00371 =H Put keys into registry
00372 
00373 put keys into Registry 
00374 
00375 Arguments:
00376 
00377 =itemize
00378 =item T<start>   : one of the predefined key (e.g. HKEY_CLASSES_ROOT)
00379 =item T<keyname> : path to the key to create
00380 =item T<name>    : subkey to create
00381 =item T<content> : it's content
00382 =noitemize
00383 /*FUNCTION*/
00384 int PutSBRegString(HKEY start,
00385                    char *keyname,
00386                    char *name,
00387                    char *content
00388 ){
00389 /*noverbatim
00390 CUT*/
00391   HKEY key;
00392   DWORD status;
00393   char logs[SSLEN];
00394   int Q;
00395 
00396 RETRY:
00397   RegCreateKeyEx(start,keyname,0,"",
00398     0,KEY_ALL_ACCESS,NULL,&key,&status);
00399   if (RegSetValueEx(key,name,0,REG_SZ,
00400     content,(DWORD)strlen(content)+1)!=ERROR_SUCCESS) {
00401     sprintf(logs, "%s\\%s\\%s",
00402                (start == LOCAL ? "HKEY_LOCAL_MACHINE" : "HKEY_CLASSES_ROOT"),keyname,name
00403            ); 
00404     Q = failReport(logs,"write");
00405     if( Q == IDTRYAGAIN )goto RETRY;
00406     if( Q == IDCONTINUE ){
00407       GlobalSuccessFlag = 0;
00408       return TRUE;
00409       }
00410     return FALSE;
00411   }
00412   return TRUE;
00413 }
00414 
00415 /*POD
00416 =H Put keys into registry
00417 
00418 put keys into Registry 
00419 
00420 Arguments:
00421 
00422 =itemize
00423 =item T<start>   : one of the predefined key (e.g. HKEY_CLASSES_ROOT)
00424 =item T<keyname> : path to the key to create
00425 =item T<name>    : subkey to create
00426 =item T<content> : it's content
00427 =noitemize
00428 /*FUNCTION*/
00429 int PutSBRegDW(HKEY start,
00430                char *keyname,
00431                char *name,
00432                DWORD DW
00433 ){
00434 /*noverbatim
00435 CUT*/
00436   HKEY key;
00437   DWORD status;
00438   char logs[SSLEN];
00439   int Q;
00440 
00441 RETRY:
00442   RegCreateKeyEx(start,keyname,0,"",
00443     0,KEY_ALL_ACCESS,NULL,&key,&status);
00444   if (RegSetValueEx(key,name,0,REG_DWORD,
00445     (BYTE *)&DW,sizeof(DWORD))!=ERROR_SUCCESS) {
00446     sprintf(logs, "%s\\%s\\%s",
00447                (start == LOCAL ? "HKEY_LOCAL_MACHINE" : "HKEY_CLASSES_ROOT"),keyname,name
00448            ); 
00449     Q = failReport(logs,"write");
00450     if( Q == IDTRYAGAIN )goto RETRY;
00451     if( Q == IDCONTINUE ){
00452       GlobalSuccessFlag = 0;
00453       return TRUE;
00454       }
00455     return FALSE;
00456   }
00457   return TRUE;
00458 }
00459 /*POD
00460 =H Get keys from registry
00461 /*FUNCTION*/
00462 char *GetRegistryKey(char *keyname,
00463                      char *name
00464   ){
00465 /*noverbatim
00466 CUT*/
00467   HKEY key;
00468   char value[SSLEN];
00469   DWORD n;
00470   
00471   char logs[SSLEN];
00472   int Q;
00473 
00474 RETRY:
00475   if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,keyname,0,KEY_ALL_ACCESS,&key)!=ERROR_SUCCESS)goto FAIL_1;
00476   n=SSLEN;
00477   value[0]='\0';
00478   if (RegQueryValueEx(key,name,NULL,NULL,value,&n)!=ERROR_SUCCESS) goto FAIL_1;
00479   value[n]='\0';
00480   RegCloseKey(key);
00481   return strdup(value);
00482 
00483 FAIL_1:
00484     sprintf(logs, "%s\\%s",keyname,name); 
00485     Q = failReport(logs,"write");
00486     if( Q == IDTRYAGAIN )goto RETRY;
00487     if( Q == IDCONTINUE ){
00488       GlobalSuccessFlag = 0;
00489       return strdup("");
00490       }
00491     return NULL;
00492 
00493 }
00494 
00495 int InstallQuestionYN(char *pszText)
00496 /* wrapper for MessageBox() */
00497 {
00498   
00499   return MessageBoxEx(NULL,
00500                       pszText,
00501                       "ScriptBasic Install",
00502                       MB_YESNO | MB_ICONQUESTION | MB_SYSTEMMODAL,
00503                       MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US)) == IDYES;
00504 }
00505 
00506 char *brushup(char *path) /* change to lower case, add slash */
00507 {
00508   int i;
00509   char buf[SSLEN];
00510   
00511   if (path==NULL) return NULL;
00512   
00513   i=0;
00514   do {
00515     buf[i]=tolower(path[i]); 
00516     if (buf[i]=='/') buf[i]='\\';
00517     i++;
00518   }while(path[i]!='\0' && isprint(path[i]));
00519   
00520   buf[i]='\0';
00521   
00522   if (buf[i-1]!='\\') {
00523     buf[i]='\\';
00524     buf[i+1]='\0';
00525   }
00526   
00527   return strdup(buf);
00528 }      
00529 
00530 void brushupinline(char *path) /* change to lower case, add slash */
00531 {
00532   int i,j,pch;
00533   
00534   if (path==NULL) return;
00535   
00536   i=j=0;
00537   pch=0;
00538   do {
00539     path[i]=tolower(path[j]); 
00540     if (path[i]=='/')path[i]='\\';
00541     if( pch != '\\' || path[i] != '\\' )i++;
00542     pch = path[j];
00543     j++;
00544   }while( path[j] != '\0' && isprint(path[j]) );
00545   
00546   path[i]='\0';
00547   return ;
00548 }      
00549 
00550 void logit(char *text) 
00551 /* 
00552 write text to log-file 
00553 text : text to write
00554 */
00555 {
00556   static FILE *log=NULL;   /* file for logging */
00557   SYSTEMTIME time;         /* time */
00558   static int oldtime;
00559   
00560   /* open log-file */
00561   if (!log) {
00562     sprintf(logfilename,"%s%s",temppath,"scriba.log");
00563     log=fopen(logfilename,"w");
00564     GetSystemTime(&time);
00565     if (log) {
00566       fprintf(log,"\n\n\n---------------------------------------------------\n"
00567         "Starting installation-log, "
00568         "hr=%d, min=%d, sec=%d, msec=%d.\n",
00569         time.wHour,time.wMinute,time.wSecond,time.wMilliseconds);
00570       oldtime=GetCurrentTime();
00571     }
00572   }
00573   
00574   if (log) {
00575     GetSystemTime(&time);
00576     if (GetCurrentTime()-oldtime>10000) {
00577       fprintf(log,"--Timestamp: hr=%d, min=%d, sec=%d, msec=%d\n",
00578         time.wHour,time.wMinute,time.wSecond,time.wMilliseconds);
00579       oldtime=GetCurrentTime();
00580     }
00581     if (text) {
00582       if (strncmp(text,"--",2)) fprintf(log,"  ");
00583       while(*text!='\0') {
00584         fputc(*text,log);
00585         if (*text=='\n' && *(text+1)!='\0') fprintf(log,"  ");
00586         text++;
00587       }
00588     }
00589     else {  /* not text ... */
00590       fprintf(log,"Closing installation-log.");
00591       fflush(log);
00592       fclose(log);
00593       log = NULL; // not to close it twice
00594     }
00595   }
00596   if (log) fflush(log);
00597 }
00598 
00599 int MyMessage(HWND handle,LPCSTR text,LPCSTR title,UINT style)
00600 /* wrapper for MessageBox() */
00601 {
00602   
00603   sprintf(logs,"--Message box: '%s'\n",text);
00604   logit(logs);
00605   
00606   return MessageBoxEx(handle,text,title,style,
00607     MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US));
00608 }
00609 
00610 /* shortcuts for end-message */
00611 #define INSTALL_CANCELLED 1
00612 #define INSTALL_ABORTED   2
00613 #define INSTALL_SUCCESS   3
00614 #define INSTALL_FAILURE   4
00615 #define REMOVE_SUCCESS    6
00616 #define REMOVE_FAILURE    7
00617 #define REMOVE_CANCELLED  8
00618 #define SILENT            9
00619 #define INSTALL_PARTIAL  10
00620 
00621 void end(int m) { /* display message and terminate */
00622   char *msg;
00623   int ret;
00624   
00625   switch(m) {
00626   case INSTALL_CANCELLED:
00627     msg="Okay, installation cancelled.\n"
00628       "No garbage has been left.";
00629     ret=FALSE;
00630     break;
00631   case INSTALL_FAILURE:
00632     msg="Installation failed.\n"
00633       "Some garbage has been left in the system.\n"
00634       "To clean it up, you better remove ScriptBasic.";
00635     ret=FALSE;
00636     break;
00637   case INSTALL_ABORTED:
00638     msg="Installation aborted.\n"
00639       "Some garbage has been left in the system !\n"
00640       "To clean it up, you better remove ScriptBasic.";
00641     ret=FALSE;
00642     break;
00643   case INSTALL_SUCCESS:
00644     progress("Install complete");
00645     msg="Installation completed successfully !\n\n"
00646         "You may now start writing ScriptBasic programs.\n\n"
00647         "Note that the PATH was altered to contain the\n"
00648         "ScriptBasic binary directory, thus you can start\n"
00649         "any BASIC program from the command line typing:\n\n"
00650         "    scriba program_name\n\n"
00651         "or just typing:\n\n"
00652         "    program_name.sb\n\n"
00653         "or just\n\n"
00654         "    program_name\n\n"
00655         "To have this effect first you have to log out and\n"
00656         "log in again. There is no need to reboot the machine.\n"
00657        
00658     ;
00659     ret=TRUE;
00660     break;
00661   case INSTALL_PARTIAL:
00662     progress("Install complete");
00663     msg="Installation completed with some errors!\n\n"
00664         "You may now start writing ScriptBasic programs.\n\n"
00665         "Note that the PATH may have been altered to contain the\n"
00666         "ScriptBasic binary directory, thus you may be successful starting\n"
00667         "any BASIC program from the command line typing:\n\n"
00668         "    scriba program_name\n\n"
00669         "or just typing:\n\n"
00670         "    program_name.sb\n\n"
00671         "or just\n\n"
00672         "    program_name\n\n"
00673         "To have this effect first you have to log out and\n"
00674         "log in again. There is no need to reboot the machine.\n\n"
00675         "The install was partial, thus some features of the install or\n"
00676         "ScriptBasic itself may not work. It is recommended to run\n"
00677         "setup.exe from an administrative account.\n"
00678        
00679     ;
00680     ret=TRUE;
00681     break;
00682   case REMOVE_SUCCESS:
00683     msg="ScriptBasic has been removed properly !";
00684     ret=TRUE;
00685     break;
00686   case REMOVE_CANCELLED:
00687     msg="Cancelled. ScriptBasic has been left intact.";
00688     ret=FALSE;
00689     break;
00690   case REMOVE_FAILURE:
00691     msg="Couldn't remove ScriptBasic properly !";
00692     ret=FALSE;
00693     break;
00694   case SILENT:
00695     ret=TRUE;
00696     goto silent;
00697   default:
00698     break;
00699   }
00700   MyMessage(NULL,msg,"ScriptBasic Install",MB_OK|MB_SYSTEMMODAL|MB_ICONINFORMATION);
00701   
00702 silent:
00703   
00704   /* close log-file */
00705   logit(NULL); 
00706   exit(ret);
00707   
00708   return;
00709 }
00710 
00711 UINT CALLBACK HookProc(HWND hdl,UINT msg,WPARAM wparam,LPARAM lparam) /* hook for save as */
00712 {
00713   if (msg==WM_INITDIALOG) {
00714     RECT rc;
00715     /* center dialog box */
00716     GetWindowRect(GetParent(hdl),&rc);
00717     SetWindowPos(GetParent(hdl),HWND_TOP,
00718       ((GetSystemMetrics(SM_CXSCREEN)-(rc.right-rc.left))/2),
00719       ((GetSystemMetrics(SM_CYSCREEN)-(rc.bottom-rc.top))/2),
00720       0,0,SWP_NOSIZE|SWP_NOACTIVATE|SWP_SHOWWINDOW);
00721     CommDlg_OpenSave_HideControl(GetParent(hdl),cmb1);
00722     CommDlg_OpenSave_HideControl(GetParent(hdl),edt1);
00723     CommDlg_OpenSave_SetControlText(GetParent(hdl),IDOK,"OK");
00724     CommDlg_OpenSave_SetControlText(GetParent(hdl),IDCANCEL,"Cancel");
00725     CommDlg_OpenSave_SetControlText(GetParent(hdl),stc4,"Install in: ");
00726     CommDlg_OpenSave_HideControl(GetParent(hdl),stc3);
00727     CommDlg_OpenSave_HideControl(GetParent(hdl),stc2);
00728     return FALSE;
00729   }             
00730   return FALSE;
00731 }
00732 
00733 BOOL CALLBACK pathdialog(HWND handle,UINT message,
00734                          WPARAM wparam,LPARAM lparam)
00735                          /* callback for choice of installation path */
00736 {
00737   int cmdid;           /* id of command */
00738   char buf[SSLEN];       /* buffer for installation-path */
00739   int offset=0;
00740   char name[SSLEN];       /* buffer for filename */
00741   OPENFILENAME fname; /* for common dialog */
00742   int ret;
00743   
00744   switch(message) {
00745   case WM_INITDIALOG:
00746     { /* center dialog box */
00747       RECT rc;
00748       
00749       GetWindowRect(handle,&rc);
00750       SetWindowPos(handle,HWND_TOP,
00751         ((GetSystemMetrics(SM_CXSCREEN)-(rc.right-rc.left))/2),
00752         ((GetSystemMetrics(SM_CYSCREEN)-(rc.bottom-rc.top))/2),
00753         0,0,SWP_NOSIZE|SWP_NOACTIVATE|SWP_SHOWWINDOW);
00754     }
00755     SetDlgItemText(handle,IDINSTPATH,pszInstallPath);
00756     return TRUE;
00757     
00758   case WM_COMMAND:
00759     cmdid=LOWORD(wparam);
00760     switch(cmdid) {
00761     case IDOK:
00762       EndDialog(handle,TRUE);
00763       GetDlgItemText(handle,IDINSTPATH,buf,SSLEN);
00764       pszInstallPath=strdup(buf);
00765       return TRUE;
00766     case IDCANCEL:
00767       EndDialog(handle,FALSE);
00768       return TRUE;
00769     case IDC_BROWSE:
00770       fname.lStructSize=sizeof(fname);
00771       fname.hwndOwner=handle;
00772       fname.hInstance=this_instance;
00773       fname.lpstrFilter="None\0+.+++\0\0";
00774       fname.lpstrCustomFilter=NULL; 
00775       fname.nMaxCustFilter=0;    
00776       fname.nFilterIndex=0; 
00777       fname.nMaxFile=SSLEN;
00778       fname.lpstrFileTitle=NULL;
00779       fname.nMaxFileTitle=0;
00780       offset=0;
00781       GetDlgItemText(handle,IDINSTPATH,buf,SSLEN);
00782       ret=GetFileAttributes(buf);
00783       if (ret==0xFFFFFFFF || !(ret & FILE_ATTRIBUTE_DIRECTORY)) {
00784         GetLogicalDriveStrings(SSLEN,buf);
00785         offset=(int)strlen(buf)+1;
00786       }
00787       fname.lpstrInitialDir=buf+offset;
00788       strcpy(name,"dummy");
00789       fname.lpstrFile=name;
00790       fname.lpstrTitle="Select ScriptBasic's directory"; 
00791       fname.Flags=OFN_HIDEREADONLY | OFN_EXPLORER | 
00792         OFN_ENABLEHOOK | OFN_ENABLETEMPLATE | OFN_NOVALIDATE;
00793       fname.lpstrDefExt=NULL; 
00794       fname.lCustData=0;
00795       fname.lpfnHook=(void *)HookProc; 
00796       fname.lpTemplateName=MAKEINTRESOURCE(IDD_EXPLANATION);
00797       if (GetOpenFileName(&fname)) {
00798         name[fname.nFileOffset]='\0';
00799         SetDlgItemText(handle,IDINSTPATH,name);
00800       }
00801       return TRUE;
00802     default:
00803       break;
00804     }
00805     default:
00806       break;
00807   }
00808   return FALSE;
00809 }
00810 
00811 void DeleteFromPath(char *Path){
00812   char *s;
00813   int i,j,k;
00814   char **PathArr;
00815   char szIDIR[SSLEN];
00816   char szFullPath[SSLEN];
00817   int slen;
00818 
00819   sprintf(logs,"--State: Current PATH=%s\n",Path);
00820   logit(logs);
00821   /* count the elements in the path */
00822   i= 0;
00823   for( s = Path ; *s ; s++ )if( *s == ';' )i++;
00824   i++; //count the last one
00825   PathArr = malloc(i*sizeof(char*));
00826   if( PathArr == NULL )return;
00827 
00828   /* split the path into an array */
00829   PathArr[0] = Path;
00830   j = 0;
00831   for( s = Path ; *s ; s++ ){
00832     if( *s == ';' ){
00833       *s = (char)0;
00834       j++;
00835       if( j < i )PathArr[j] = s+1;
00836       }
00837     }
00838 
00839   /* search for the actual path, it may already be in the path */
00840   sprintf(string,"%sbin\\",pszInstallPath);
00841   slen = (int)strlen(string)-1;
00842   GetFullPathName(string,SSLEN,szIDIR,&s);
00843   for( j = 0 ; j < i ; j++ ){
00844     GetFullPathName(PathArr[j],SSLEN,szFullPath,&s);
00845     // compare the path with and without the terminating backslash
00846     if( ! stricmp(szFullPath,szIDIR) || !strnicmp(szFullPath,szIDIR,slen) ){
00847       sprintf(logs,"--Progress: removing >>%s<< from the path\n",PathArr[j]);
00848       logit(logs);
00849       PathArr[j] = NULL;
00850       }
00851     }
00852   *szFullPath = (char)0;
00853   k = 0;
00854   for( j = 0 ; j < i ; j++ ){
00855     if( PathArr[j] ){
00856       if( k )strcat(szFullPath,";");
00857       k = 1;
00858       strcat(szFullPath,PathArr[j]);
00859       }
00860     }
00861   strcpy(Path,szFullPath);
00862 
00863   }
00864 
00865 void DeleteFromPathEx(char *Path,
00866                       char *Ext){
00867   char *s;
00868   int i,j,k;
00869   char **PathArr;
00870   char szFullPath[SSLEN];
00871 
00872   sprintf(logs,"--State: Current PATHEXT=%s\n",Path);
00873   logit(logs);
00874   /* count the elements in the path */
00875   i= 0;
00876   for( s = Path ; *s ; s++ )if( *s == ';' )i++;
00877   i++; //count the last one
00878   PathArr = malloc(i*sizeof(char*));
00879   if( PathArr == NULL )return;
00880 
00881   /* split the path into an array */
00882   PathArr[0] = Path;
00883   j = 0;
00884   for( s = Path ; *s ; s++ ){
00885     if( *s == ';' ){
00886       *s = (char)0;
00887       j++;
00888       if( j < i )PathArr[j] = s+1;
00889       }
00890     }
00891 
00892   /* search for the actual path, it may already be in the path */
00893   for( j = 0 ; j < i ; j++ ){
00894     // compare the path with and without the terminating backslash
00895     if( ! stricmp(PathArr[j],Ext) ){
00896       sprintf(logs,"--Progress: removing >>%s<< from the path ext\n",PathArr[j]);
00897       logit(logs);
00898       PathArr[j] = NULL;
00899       }
00900     }
00901   *szFullPath = (char)0;
00902   k = 0;
00903   for( j = 0 ; j < i ; j++ ){
00904     if( PathArr[j] ){
00905       if( k )strcat(szFullPath,";");
00906       k = 1;
00907       strcat(szFullPath,PathArr[j]);
00908       }
00909     }
00910   strcpy(Path,szFullPath);
00911 
00912   }
00913 
00914 int MyRegs(int mode) /* add or delete entries to or from registry */
00915 {
00916   int success=TRUE;
00917   char string[SSLEN];   /* multi-purpose-string */
00918   char windir[SSLEN];   /* windows-directory */
00919   char *Path,*PathEx;
00920 
00921   switch(mode) {
00922   case INSTALL:
00923     /* registering uninstall program */
00924     progress("Registering uninstall-program");
00925     if( ! PutSBRegString(LOCAL,UNINSTALL BASIC_NAME,"DisplayName",BASIC_NAME) ) return 0;
00926     sprintf(string,"%s%s %s",pszInstallPath,BASIC_SETUP,"remove");
00927     if( ! PutSBRegString(LOCAL,UNINSTALL BASIC_NAME,"UninstallString",string) ) return 0;
00928     progress("Adding defaults to registry.");
00929     /* make changes in registry, put in defaults */
00930     if( ! PutSBRegString(LOCAL,SOFT BASIC_NAME,"path",pszInstallPath) ) return 0;
00931     sprintf(string,"%s%s",pszInstallPath,"bin\\scriba.conf");
00932     if( ! PutSBRegString(LOCAL,SOFT BASIC_NAME,"config",string) ) return 0;
00933     progress("Registering version in registry");
00934     if( ! PutSBRegDW(LOCAL,SOFT BASIC_NAME,"major",MAJOR) ) return 0;
00935     if( ! PutSBRegDW(LOCAL,SOFT BASIC_NAME,"minor",MINOR) ) return 0;
00936     progress("Registering build number in registry");
00937     if( ! PutSBRegDW(LOCAL,SOFT BASIC_NAME,"build",BUILD) )return 0;
00938     
00939     progress("Registering file extension.");
00940     /* change context-menu */
00941     if( ! PutRegistryKey(ROOT,BASIC_EXTENSION,"",BASIC_NAME) ) return 0;
00942     progress("Registering application type");
00943     if(  ! PutRegistryKey(ROOT,BASIC_NAME,"","ScriptBasic Program") ) return 0;
00944     progress("Registering application name");
00945     if(  ! PutRegistryKey(ROOT,BASIC_NAME"\\DefaultIcon","",app("bin\\"BASIC_ICON)) ) return 0;
00946     progress("Registering icon");
00947     if( ! PutRegistryKey(ROOT,BASIC_EXTENSION"\\ShellNew","NullFile","") )return 0;
00948     if( ! PutRegistryKey(ROOT,BASIC_NAME"\\shell\\open","","&Execute") )return 0;
00949     if( ! PutRegistryKey(ROOT,BASIC_NAME"\\shell\\open\\command","", app("BIN\\"BASIC_EXE" \"%1\"")) ) return 0;
00950 
00951     Path = GetRegistryKey("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment","Path");
00952     if( Path == NULL )return 0;
00953     if( *Path ){
00954       /* Delete the actual directory from the path if this is there */
00955       DeleteFromPath(Path);
00956       // create the new path where the new directory is the first one
00957       sprintf(string,"%sbin\\;%s",pszInstallPath,Path);
00958       sprintf(logs,"--Progress: Setting PATH=%s\n",string);
00959       logit(logs);
00960       // put the new path into the registry. Note that this comes alive only after logout-login
00961       if( ! PutRegistryEKey(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment","Path",string) )return 0;
00962       }
00963     PathEx = GetRegistryKey("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment","PATHEXT");
00964     if( *PathEx ){
00965       /* Delete the actual directory from the path if this is there */
00966       DeleteFromPathEx(PathEx,".SB");
00967       // create the new path extension
00968       sprintf(string,"%s;.SB",PathEx);
00969       sprintf(logs,"--Progress: Setting PATHEXT=%s\n",string);
00970       logit(logs);
00971       // put the new path extension
00972       PutRegistryKey(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment","PATHEXT",string);
00973       }
00974     progress("Linking to root-Menu");
00975     if( ! PutRegistryKey(ROOT,BASIC_NAME"\\shell\\New","","&Edit") ) return 0;
00976     GetWindowsDirectory(string,SSLEN);
00977     sprintf(windir,"%s%s",brushup(string),"Notepad.exe \"%1\"");
00978     if( ! PutRegistryKey(ROOT,BASIC_NAME"\\shell\\New\\command","",windir)  ) return 0;
00979     
00980     return TRUE;
00981   case REMOVE:
00982     /* registering uninstall program */
00983     progress("Removing uninstall registering");
00984     success=DeleteRegistryKey(LOCAL,UNINSTALL,BASIC_NAME);
00985     progress("Removing defaults from registry.");
00986     /* make changes in registry, put in defaults */
00987     success=DeleteRegistryKey(LOCAL,SOFT, BASIC_NAME) && success;
00988     
00989     progress("Deregistering file extension.");
00990     /* change context-menu */
00991     success=DeleteRegistryKey(ROOT,BASIC_EXTENSION,"ShellNew") && success;
00992     success=DeleteRegistryKey(ROOT,BASIC_EXTENSION,"") && success;
00993     progress("Shell extensions deregistering");
00994     success=DeleteRegistryKey(ROOT,BASIC_NAME"\\shell\\open","command")&& success;
00995     success=DeleteRegistryKey(ROOT,BASIC_NAME"\\shell","open") && success;
00996     success=DeleteRegistryKey(ROOT,BASIC_NAME"\\shell\\new","command")&& success;
00997     success=DeleteRegistryKey(ROOT,BASIC_NAME"\\shell","new") && success;
00998     success=DeleteRegistryKey(ROOT,BASIC_NAME,"shell") && success;
00999     success=DeleteRegistryKey(ROOT,BASIC_NAME,"DefaultIcon") && success;
01000     success=DeleteRegistryKey(ROOT,BASIC_NAME,"") && success;
01001     progress("Shell extensions deregistered");
01002 
01003     Path = GetRegistryKey("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment","Path");
01004     /* Delete the actual directory from the path if this is there */
01005     DeleteFromPath(Path);
01006     // create the new path where the new directory is the first one
01007     sprintf(logs,"--Progress: Setting PATH=%s\n",string);
01008     logit(logs);
01009     // put the new path into the registry. Note that this comes alive only after logout-login
01010     PutRegistryEKey(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment","Path",Path);
01011 
01012     PathEx = GetRegistryKey("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment","PATHEXT");
01013     /* Delete the actual directory from the path if this is there */
01014     DeleteFromPathEx(PathEx,".SB");
01015     // create the new path where the new directory is the first one
01016     sprintf(logs,"--Progress: Setting PATHEXT=%s\n",string);
01017     logit(logs);
01018     // put the new path into the registry. Note that this comes alive only after logout-login
01019     PutRegistryKey(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment","PATHEXT",PathEx);
01020     progress("Unlinking to root-Menu");
01021     
01022     return success;
01023   }
01024   return success;
01025 }
01026 
01027 
01028 BOOL CALLBACK progressdialog(HWND handle,UINT message,
01029                              WPARAM wparam,LPARAM lparam)
01030                              /* callback for cprogress dialog */
01031 {
01032   
01033   switch(message) {
01034   case WM_INITDIALOG:
01035     { /* center dialog box */
01036       RECT rc;
01037       
01038       GetWindowRect(handle,&rc);
01039       SetWindowPos(handle,HWND_TOP,
01040         ((GetSystemMetrics(SM_CXSCREEN)-(rc.right-rc.left))/2),
01041         ((GetSystemMetrics(SM_CYSCREEN)-(rc.bottom-rc.top))/2),
01042         0,0,SWP_NOSIZE|SWP_NOACTIVATE|SWP_SHOWWINDOW);
01043     }
01044     return TRUE;
01045   default:
01046     break;
01047   }
01048   return FALSE;
01049 }
01050 
01051 
01052 int timerid;
01053 MSG timermsg;
01054 RECT rc;
01055 static int count=0;
01056 static HWND progressbox=NULL;   /* handle of progress dialog */
01057 static HWND hwndPB=NULL; /* handle of progress bar */
01058 char string[SSLEN];             /* multi-purpose string */
01059 int thumb;  // height of scroll bar arrow 
01060 
01061 void progress(char *msg) /* show progress */
01062 {
01063   int i;
01064   int millsec = 5;
01065   count++;
01066   
01067   /* create progress dialog */
01068   if (progressbox==NULL) {
01069     InitCommonControls();
01070     progressbox=CreateDialog((HANDLE)this_instance,
01071       MAKEINTRESOURCE(IDD_PROGRESSDIALOG),
01072       (HANDLE)NULL,
01073       (DLGPROC)progressdialog);
01074     GetClientRect(progressbox,&rc); 
01075     thumb= 8 ;//GetSystemMetrics(SM_CYVSCROLL); 
01076     hwndPB=CreateWindowEx(WS_EX_TOPMOST,       // extended window style
01077                           PROGRESS_CLASS,      // registered class name
01078                           (LPSTR)NULL,         // window name
01079                           WS_CHILD|WS_VISIBLE|PBS_SMOOTH, // window style
01080                           rc.left+thumb,       // horizontal position of window
01081                           rc.bottom- 3*thumb,  // vertical position of window
01082                           rc.right-2*thumb,    // window width
01083                           2*thumb,             // window height
01084                           progressbox,         // handle to parent or owner window
01085                           (HMENU) 0,           // menu handler
01086                           this_instance,       // handle to application instance
01087                           NULL                 // window creation data
01088                           );
01089     SendMessage(hwndPB, PBM_SETRANGE, 0, MAKELPARAM(0,total_progress*progress_wait/millsec)); 
01090     SendMessage(hwndPB, PBM_SETSTEP, (WPARAM) 1, 0);
01091     /* actually display the window */
01092     ShowWindow(progressbox,SW_SHOW);
01093   }
01094   
01095   /* change text */
01096   if (msg) SetDlgItemText(progressbox,IDC_PROGRESSTEXT,msg);
01097   
01098   /* write to logfile */
01099   if (msg) {
01100     sprintf(logs,"--Progress: '%s'\n",msg);
01101     logit(logs);
01102   }
01103   
01104   /* set heading of progress window */
01105   sprintf(string,"Work in progress ... step %d of %d",count,total_progress);
01106   SendMessage((HWND)progressbox,(UINT)WM_SETTEXT,0,(LPARAM)(LPCTSTR)string);
01107 
01108   for( i=0 ; i < progress_wait ; i+= millsec ){
01109     /* advance progress count */
01110     SendMessage(hwndPB, PBM_STEPIT, 0, 0); 
01111     /* wait a bit ... */
01112     timerid=(int)SetTimer(NULL,0,millsec,(TIMERPROC) NULL);
01113     GetMessage((LPMSG)&timermsg,NULL,WM_TIMER,WM_TIMER);
01114     KillTimer(NULL,timerid);
01115     }
01116 }
01117 
01118 void noprogress(char *msg){
01119   /* change text */
01120   if (msg) SetDlgItemText(progressbox,IDC_PROGRESSTEXT,msg);
01121   
01122   /* write to logfile */
01123   if (msg) {
01124     sprintf(logs,"--Progress: '%s'\n",msg);
01125     logit(logs);
01126   }
01127   
01128   /* wait a bit ... */
01129   timerid=(int)SetTimer(NULL,0,progress_wait,(TIMERPROC) NULL);
01130   GetMessage((LPMSG)&timermsg,NULL,WM_TIMER,WM_TIMER);
01131   KillTimer(NULL,timerid);
01132   }
01133 
01134 typedef struct linkinfo {
01135   int folder; /* registry key */
01136   char *link; /* name of link */
01137   char *file; /* name of file */
01138   char *desc; /* description of link */
01139   char *icon; /* name of icon for link */
01140   int removeonly; /* true, if icon should be removed but not installed */
01141   char *relative_path; /* relative path beneath the install path */
01142 } LINKINFO;
01143 
01144 
01145 HRESULT CreateShellLink(LINKINFO *li,char *path)
01146 /* 
01147 stolen from win32 SDK Help: Create a shell-link 
01148 li    : points to LINKINFO structure containing all infos about link 
01149 path  : Full pathname for objects
01150 */
01151 { 
01152   HRESULT hres;                /* return value */
01153   IShellLink* psl;             /* pointer to new shell-link */
01154   LPITEMIDLIST pidl;           /* path id */
01155   char PathLink[MAX_PATH];     /* path name */
01156   char string[SSLEN];          /* multi-purpose string */
01157   static int first=TRUE;
01158   
01159   /* make filename from registry folder constant */
01160   hres=SHGetSpecialFolderLocation(NULL,li->folder,&pidl);
01161   if (!SUCCEEDED(hres)) return hres;
01162   SHGetPathFromIDList(pidl,PathLink);
01163   strcat(PathLink,"\\");
01164   strcat(PathLink,li->link);
01165   
01166   /* initialize COM-library */
01167   if (first) {
01168     CoInitialize(NULL);
01169     first=FALSE;
01170   }
01171   
01172   /* Get a pointer to the IShellLink interface. */
01173   hres=CoCreateInstance(&CLSID_ShellLink,NULL, 
01174     CLSCTX_INPROC_SERVER,&IID_IShellLink,&psl); 
01175   if (SUCCEEDED(hres)) { 
01176     IPersistFile* ppf; 
01177     
01178     /* Set the path to the shortcut target */
01179     sprintf(string,"%s%s",path,li->file);
01180     psl->lpVtbl->SetPath(psl,string); 
01181     
01182     /* add description */
01183     psl->lpVtbl->SetDescription(psl,li->desc); 
01184     
01185     /* set working directory */
01186     psl->lpVtbl->SetWorkingDirectory(psl,path);
01187     
01188     /* set icon */
01189     if (li->icon[1]) {
01190       sprintf(string,"%s%s",path,li->icon);
01191       psl->lpVtbl->SetIconLocation(psl,string,0);
01192     } else {
01193       GetSystemDirectory(string,SSLEN);
01194       strcat(string,"\\shell32.dll");
01195       psl->lpVtbl->SetIconLocation(psl,string,li->icon[0]);
01196     }
01197     
01198     /* Query IShellLink for the IPersistFile interface for saving the 
01199     shortcut in persistent storage. */
01200     hres=psl->lpVtbl->QueryInterface(psl,&IID_IPersistFile,&ppf); 
01201     
01202     if (SUCCEEDED(hres)) { 
01203       WORD wsz[MAX_PATH]; 
01204       
01205       /* Ensure that the string is ANSI. */
01206       MultiByteToWideChar(CP_ACP,0,PathLink,-1,wsz,MAX_PATH); 
01207       
01208       /* Save the link by calling IPersistFile::Save. */
01209       hres=ppf->lpVtbl->Save(ppf,wsz,TRUE);
01210       ppf->lpVtbl->Release(ppf); 
01211     } 
01212     psl->lpVtbl->Release(psl); 
01213   } 
01214   return hres; 
01215 } 
01216 
01217 
01218 HRESULT DeleteShellLink(LINKINFO *li)
01219 /* 
01220 Delete a shell-link 
01221 li    : points to LINKINFO structure containing all infos about link 
01222 */
01223 { 
01224   HRESULT hres;                /* return value */
01225   LPITEMIDLIST pidl;           /* path id */
01226   char PathLink[MAX_PATH];     /* path name */
01227   
01228   /* make filename from folder constant */
01229   hres=SHGetSpecialFolderLocation(NULL,li->folder,&pidl);
01230   if (!SUCCEEDED(hres)) return hres;
01231   SHGetPathFromIDList(pidl,PathLink);
01232   strcat(PathLink,"\\");
01233   strcat(PathLink,li->link);
01234   
01235   sprintf(logs,"--Deleting '%s'\n",PathLink);
01236   logit(logs);
01237   return DeleteFile(PathLink);
01238 } 
01239 
01240 
01241 int MyLinks(int mode) /* add or remove shell links */
01242 {
01243   int success=TRUE;
01244   char string[SSLEN];
01245   LPITEMIDLIST pidl;           /* path id */
01246   char PathLink[MAX_PATH];     /* path name */
01247   int res;
01248   static LINKINFO li[]={
01249 //    {CSIDL_PROGRAMS        ,BASIC_NAME"\\"BASIC_NAME".LNK",BASIC_EXE       ,"Link to "BASIC_NAME      ,BASIC_ICON,FALSE,"BIN\\"},
01250 //    {CSIDL_PROGRAMS        ,BASIC_NAME".LNK"              ,BASIC_EXE       ,"Link to "BASIC_NAME      ,BASIC_ICON,FALSE,"BIN\\"},
01251     {CSIDL_PROGRAMS        ,BASIC_NAME"\\Users' Guide.LNK","ug.chm"        ,"Link to Users' Guide"    ,BASDOC_ICON    ,FALSE,"DOC\\"},
01252     {CSIDL_PROGRAMS        ,BASIC_NAME"\\Readme.LNK"      ,"readme.txt"    ,"Link to README.TXT"      ,"\026"    ,FALSE,""      },
01253     {CSIDL_PROGRAMS        ,BASIC_NAME"\\Install log.LNK" ,"install.log"    ,"Link to install.log"      ,"\026"    ,FALSE,""      },
01254     {CSIDL_DESKTOPDIRECTORY,"Users' Guide.LNK"            ,"ug.chm"        ,"Link to Users' Guide"    ,BASDOC_ICON    ,FALSE,"DOC\\"},
01255 
01256     {CSIDL_PROGRAMS,BASIC_NAME"\\Configure\\Configuration File.LNK"  ,"scriba.conf.txt","Configuration File"    ,"\026"    ,FALSE,"\\"},
01257     {CSIDL_PROGRAMS,BASIC_NAME"\\Configure\\Compile Configuration.LNK", "compconf.sb","Compile the configuration.sb", BASIC_ICON,FALSE,"EXAMPLES\\"},
01258 
01259 #define MODUDOC(X,Y) \
01260     {CSIDL_PROGRAMS,BASIC_NAME"\\Documentation\\" X ".LNK", "mod_" Y ".chm","Link to mod_" X ".chm", "\027",FALSE,"DOC\\"},\
01261 
01262 MODUDOC("Debugging BASIC programs","dbg")
01263 MODUDOC("Berkeley Database Module","bdb")
01264 MODUDOC("Writing Cgi","cgi")
01265 MODUDOC("Console IO","cio")
01266 MODUDOC("CURL Handling URLs","curl")
01267 MODUDOC("Creating PNG Graphics","gd")
01268 MODUDOC("Hash Module","hash")
01269 MODUDOC("Multi-thread Module","mt")
01270 MODUDOC("MySQL Module","mysql")
01271 MODUDOC("Windows NT Functions","nt")
01272 MODUDOC("ODBC Module","odbc")
01273 MODUDOC("Regular Expressions","re")
01274 MODUDOC("Extra Tools","t")
01275 MODUDOC("Compressing Files","zlib")
01276 MODUDOC("Handling XML Data","xml")
01277 #undef MODUDOC
01278 
01279 #include "examples.c"
01280 
01281     { 0                    , NULL                         ,NULL            ,NULL                      ,NULL      ,FALSE, ""    }
01282   };
01283   int i;  
01284   
01285   if (mode==INSTALL) {
01286     /* make filename from registry folder constant */
01287     SHGetSpecialFolderLocation(NULL,CSIDL_PROGRAMS,&pidl);
01288     SHGetPathFromIDList(pidl,PathLink);
01289     strcat(PathLink,"\\"BASIC_NAME);
01290     res=CreateDirectory(PathLink,NULL);
01291     strcat(PathLink,"\\Documentation");
01292     res=CreateDirectory(PathLink,NULL);
01293 
01294     SHGetSpecialFolderLocation(NULL,CSIDL_PROGRAMS,&pidl);
01295     SHGetPathFromIDList(pidl,PathLink);
01296     strcat(PathLink,"\\"BASIC_NAME);
01297     strcat(PathLink,"\\Examples");
01298     res=CreateDirectory(PathLink,NULL);
01299 
01300     SHGetSpecialFolderLocation(NULL,CSIDL_PROGRAMS,&pidl);
01301     SHGetPathFromIDList(pidl,PathLink);
01302     strcat(PathLink,"\\"BASIC_NAME);
01303     strcat(PathLink,"\\Configure");
01304     res=CreateDirectory(PathLink,NULL);
01305   }
01306 
01307 
01308   for( i=0 ; li[i].link ; i++ ) {
01309     if (mode==INSTALL && ! li[i].removeonly) {
01310       sprintf(string,"Adding %s",li[i].desc);
01311       progress(string);
01312       DeleteShellLink(li+i);/* just in case it was already there from a previous installation */
01313       if( *li[i].relative_path )sprintf(string,"%s%s",pszInstallPath,li[i].relative_path);else strcpy(string,pszInstallPath);
01314       success=SUCCEEDED(CreateShellLink(li+i,string)) && success;
01315     }
01316     else {
01317       sprintf(string,"removing %s",li[i].desc);
01318       progress(string);
01319       success=SUCCEEDED(DeleteShellLink(li+i)) && success;
01320     }
01321   }
01322   if (mode!=INSTALL) {
01323     /* make filename from registry folder constant */
01324     SHGetSpecialFolderLocation(NULL,CSIDL_PROGRAMS,&pidl);
01325     SHGetPathFromIDList(pidl,PathLink);
01326     strcat(PathLink,"\\"BASIC_NAME);
01327     file_deltree(PathLink);
01328   }
01329   return success;
01330 }
01331 
01332 int MyFiles(int mode) /* copy or delete files */
01333 {
01334 
01335   gzFile fp;
01336   FILE *fo;
01337   char *s;
01338   int success=TRUE;
01339   char buf[SSLEN];
01340   char dirbuf[SSLEN];
01341   unsigned char *fbuf;
01342   long flen;
01343   int save_pw;
01344 
01345   switch(mode) {
01346     
01347   case INSTALL:
01348     strcpy(string,_pgmptr);
01349     s = string + strlen(string);
01350     while( *s != '\\' )s--;
01351     s++;
01352     *s = (char)0;
01353     strcat(string,GZFILE);
01354 
01355     fp = gzopen(string,"rb");
01356     if( fp == NULL ){
01357       sprintf(string,"Failed to open the installation file \"%s\"!\n"
01358               "This file has to be in the same directory as the program setup.exe!",GZFILE);
01359       MyMessage(NULL,string,INSTALL_HEADING,MB_STYLE);
01360       end(INSTALL_FAILURE);
01361       }
01362     progress("Installing files");
01363     save_pw = progress_wait;
01364     progress_wait = 2;
01365     do{
01366       gzgets(fp,buf,SSLEN);
01367       buf[strlen(buf)-1] = (char)0;
01368       sprintf(string,"Installing %s",buf);
01369       noprogress(string);
01370       sprintf(string,"%s/%s",pszInstallPath,buf);
01371       strcpy(dirbuf,string);
01372       s = dirbuf + strlen(dirbuf);
01373       while( *s != '\\' && *s != '/' )s--;
01374       *s = (char)0;
01375       file_MakeDirectory(dirbuf);
01376       brushupinline(string);
01377       while( file_exists(string) && ! DeleteFile(string) ){
01378         sprintf(buf,"The file %s exists and I can not overwrite it. If you want to go on with\n"
01379                     "the installation of ScriptBasic close all applications that may use this file\n\n"
01380                     "Do you want to continue the installation?\n",string);
01381         if( ! InstallQuestionYN(buf) ){
01382           end(INSTALL_CANCELLED);
01383           }
01384         
01385         }
01386       fo = fopen(string,"wb");
01387       gzgets(fp,buf,SSLEN);
01388       flen = atoi(buf);
01389       fbuf = malloc(flen);
01390       if( fbuf == NULL ){
01391         sprintf(string,"Memory allocation failed during installation.");
01392         MyMessage(NULL,string,INSTALL_HEADING,MB_STYLE);
01393         end(INSTALL_FAILURE);
01394         }
01395       if( gzread(fp,fbuf,flen) < flen ){
01396         sprintf(string,"The installation file \"%s\" is corrupt!\n",GZFILE);
01397         MyMessage(NULL,string,INSTALL_HEADING,MB_STYLE);
01398         end(INSTALL_FAILURE);
01399         }
01400       fwrite(fbuf,1,flen,fo);
01401       fclose(fo);
01402       }while( ! gzeof(fp) );
01403     gzclose(fp);
01404     sprintf(string,"%s\\setup.exe",pszInstallPath);
01405     logit("Copying the setup.exe into the install directory in case uninstall is needed.\n");
01406     CopyFile(_pgmptr,string,FALSE);
01407     progress_wait = save_pw;
01408     break;
01409   case REMOVE:
01410     file_deltree(pszInstallPath);
01411     break;
01412   default: 
01413     break;
01414   }
01415   return success;
01416 }    
01417 
01418 void InstallScriptBasic(){
01419   char *pszStartMessage;
01420   int success;
01421   char execvarg[SSLEN];
01422   STARTUPINFO SupInfo;
01423   PROCESS_INFORMATION ProcInfo;
01424   FILE *fp;
01425   char *s;
01426 
01427   GlobalSuccessFlag = 1;
01428 
01429   SupInfo.cb = sizeof(SupInfo);
01430   SupInfo.lpReserved = NULL;
01431   SupInfo.lpDesktop = NULL;
01432   SupInfo.lpTitle = NULL;
01433   SupInfo.dwFlags = 0;
01434   SupInfo.cbReserved2 = 0;
01435   SupInfo.lpReserved2 = NULL;
01436 
01437   // before doing anything else, check that the cab file is in place
01438   strcpy(string,_pgmptr);
01439   s = string + strlen(string);
01440   while( *s != '\\' )s--;
01441   s++;
01442   *s = (char)0;
01443   strcat(string,GZFILE);
01444      
01445   fp = fopen(string,"rb");
01446   if( fp == NULL ){
01447     sprintf(string,"Failed to open the installation file \"%s\"!\n"
01448             "This file has to be in the directory where the program 'setup.exe' is!",GZFILE);
01449     MyMessage(NULL,string,INSTALL_HEADING,MB_STYLE);
01450     end(INSTALL_FAILURE);
01451     }
01452   fclose(fp);
01453   /* set advance for progresscount */
01454   total_progress=40;
01455 
01456   if( dwMajor ){//minor and build can be zero
01457     if( dwMajor > MAJOR ||
01458         (dwMajor == MAJOR &&
01459           (dwMinor > MINOR || (dwMinor == MINOR && dwBuild > BUILD)))){
01460       pszStartMessage = "This program will install ScriptBasic " VERSION_TEXT "\n\n"
01461                         "There is a newer version of ScriptBasic installed on this system.\n"
01462                         "It is recommended that you use the newer version.\n"
01463                         "If you want to downgrade your installation it is recommended that you\n"
01464                         "first uninstall the newer version using the uninstaller of that\n"
01465                         "version and install ScriptBasic " VERSION_TEXT " only after the\n"
01466                         "newer version was removed.\n\n"
01467                         "This install process will install ScriptBasic but will not remove\n"
01468                         "the newer version. The newer version may remain on the system\n"
01469                         "unusable and uninstallable by automatic remover program.\n\n"
01470                         "If you decide to go on with the installation exit all programs\n"
01471                         "that may access and lock any ScriptBasic files. This also means to\n"
01472                         "stop the Eszter SB Application Engine in case it is running.\n\n"
01473                         "Do you want to perform the installation without removing the newer version?";
01474       }else{
01475       if( dwMajor == MAJOR && dwMinor == MINOR && dwBuild == BUILD ){
01476         pszStartMessage = "This program will install ScriptBasic " VERSION_TEXT "\n\n"
01477                           "The same version is already installed on this system.\n"
01478                           "If that version was corrupted and you want to reinstall\n"
01479                           "ScriptBasic you can, however you may loose changes to the\n"
01480                           "configuration you made since last setup.\n\n"
01481                           "It is recommended that you save your old configuration file\n"
01482                           "before continuing the installation.\n\n"
01483                           "If you decide to go on with the installation exit all programs\n"
01484                           "that may access and lock any ScriptBasic files. This also means to\n"
01485                           "stop the Eszter SB Application Engine in case it is running.\n\n"
01486                           "Do you want to perform the installation?";
01487         }else{
01488         pszStartMessage = "This program will install ScriptBasic " VERSION_TEXT "\n\n"
01489                           "There is an older version already installed on this system.\n"
01490                           "You can upgrade the older version of \n"
01491                           "ScriptBasic, however you may loose changes to the\n"
01492                           "configuration you made since last setup.\n\n"
01493                           "It is recommended that you save your old configuration file\n"
01494                           "before continuing the installation\n\n"
01495                         "If you decide to go on with the installation exit all programs\n"
01496                         "that may access and lock any ScriptBasic files. This also means to\n"
01497                         "stop the Eszter SB Application Engine in case it is running.\n\n"
01498                           "Do you want to perform the installation?";
01499         }
01500       }
01501     }else{
01502     pszStartMessage = "This program will install ScriptBasic " VERSION_TEXT "\n\n"
01503                       "If you decide to go on with the installation exit all other programs.\n\n"
01504                       "Do you want to perform the installation?";
01505     }
01506   if( ! InstallQuestionYN(pszStartMessage) ){
01507     end(INSTALL_CANCELLED);
01508     }
01509 
01510 RETRY_INSTALL_PATH:
01511   if( pszInstallPath == NULL )pszInstallPath = DEFAULT_PATH;
01512 
01513   cancel=!DialogBox((HANDLE)this_instance,MAKEINTRESOURCE(IDD_PATHDIALOG),(HWND)NULL,(DLGPROC)pathdialog);
01514     
01515   if( cancel )end(INSTALL_CANCELLED);
01516 
01517   pszInstallPath = brushup(pszInstallPath);
01518   sprintf(logs,"--Install path='%s'",pszInstallPath);
01519   logit(logs);
01520    
01521   /* check for disk-space */
01522   {
01523     DWORD spc,bps,frcl,tncl;
01524     float total;
01525     int answer;
01526       
01527     sprintf(string,"%c:\\",*pszInstallPath);
01528     GetDiskFreeSpace(string,&spc,&bps,&frcl,&tncl);
01529     total=(float)frcl*spc*bps/1024;
01530     if (total<KBNEEDED) {
01531       sprintf(string,"Free disk space is only %g kB!\n"
01532         "Proceed anyway?\n\n"
01533 "Press \"Yes\" if you want to install ScriptBasic into the selected\n"
01534 "directory even though there is not enough space on the disk.\n"
01535 "It is recommended to press \"No\" to return to the directory\n"
01536 "selection dialog and select a directory on a different disk\n"
01537 "with more space or to select the same directory again after\n"
01538 "you deleted some unwanted files to make more room.\n"
01539 "In the latter case SETUP will examine the available space again.\n"
01540 "To install ScriptBasic you need approximately %dMB free space.\n"
01541         ,total,KBNEEDED / 1024 + 1);
01542       answer=MyMessage(NULL,string,INSTALL_HEADING,
01543         MB_YESNO | MB_SYSTEMMODAL | MB_ICONINFORMATION);
01544       if (answer==IDNO) goto RETRY_INSTALL_PATH;
01545     }
01546   } 
01547    
01548   success = MyRegs(INSTALL);
01549   if (!success) {
01550     MyMessage(NULL,"Failed to make entries in the Registry !",
01551       INSTALL_HEADING,MB_STYLE);
01552     end(INSTALL_FAILURE);
01553   }
01554 
01555   /* create directories */
01556   progress("Creating directories and copying files.");
01557   CreateDirectory(pszInstallPath,NULL);
01558   success=MyFiles(INSTALL);
01559   if (!success) {
01560     MyMessage(NULL,"Couldn't copy files !", INSTALL_HEADING,MB_STYLE);
01561     end(INSTALL_FAILURE);
01562     }
01563     
01564   /* create shell links */
01565   success=MyLinks(INSTALL);
01566   if (!success) {
01567     MyMessage(NULL,"Failed to add entry to the start-Menu !",
01568       INSTALL_HEADING,MB_STYLE);
01569     end(INSTALL_FAILURE);
01570   }
01571 
01572   // edit the configuration file and then compile it
01573   sprintf(string,"%sbin\\scriba.exe",pszInstallPath);
01574   sprintf(execvarg,"%sbin\\scriba.exe %sbin\\configurer.sb %s",pszInstallPath,pszInstallPath,pszInstallPath);
01575 
01576   CreateProcess(string,
01577                 execvarg,
01578                 NULL,
01579                 NULL,
01580                 FALSE,
01581                 CREATE_NO_WINDOW,
01582                 NULL,
01583                 pszInstallPath,
01584                 &SupInfo,
01585                 &ProcInfo
01586                );
01587   Sleep(2000);
01588   CloseHandle(ProcInfo.hProcess);
01589 
01590   logit(NULL); // close the log file
01591   sprintf(string,"%sinstall.log",pszInstallPath);
01592   CopyFile(logfilename,string,FALSE);
01593 
01594   /* installation successfull ! */
01595   if( GlobalSuccessFlag )
01596     end(INSTALL_SUCCESS);
01597   end(INSTALL_PARTIAL);
01598 
01599   }
01600 
01601 void RemoveScriptBasic(){
01602   char *pszStartMessage;
01603   STARTUPINFO SupInfo;
01604   PROCESS_INFORMATION ProcInfo;
01605   char execvarg[SSLEN];
01606 
01607   total_progress = 33;
01608   SupInfo.cb = sizeof(SupInfo);
01609   SupInfo.lpReserved = NULL;
01610   SupInfo.lpDesktop = NULL;
01611   SupInfo.lpTitle = NULL;
01612   SupInfo.dwFlags = 0;
01613   SupInfo.cbReserved2 = 0;
01614   SupInfo.lpReserved2 = NULL;
01615 
01616   if( dwMajor == MAJOR && dwMinor == MINOR && dwBuild == BUILD ){
01617     pszStartMessage = "This program will uninstall ScriptBasic " VERSION_TEXT "\n\n"
01618                       "Do you want to remove ScriptBasic?";
01619     if( ! InstallQuestionYN(pszStartMessage) ){
01620       end(INSTALL_CANCELLED);
01621       }
01622     }else{
01623     pszStartMessage = "This program should be used to remove ScriptBasic " VERSION_TEXT "\n"
01624                       "The currently installed version is not the one that this program\n"
01625                       "can uninstall. Use the appropriate version of the SETUP.EXE that\n"
01626                       "was used to install ScriptBasic.";
01627     MyMessage(NULL,pszStartMessage,"ScriptBasic Install",MB_OK|MB_SYSTEMMODAL|MB_ICONINFORMATION);
01628 
01629     end(INSTALL_CANCELLED);
01630     }
01631   pszInstallPath = GetSBRegString("path");
01632 
01633   // remove the sbhttpd service
01634   sprintf(string,"%sbin\\sbhttpd.exe",pszInstallPath);
01635   sprintf(execvarg,"%sbin\\sbhttpd.exe -remove",pszInstallPath);
01636 
01637   CreateProcess(string,
01638                 execvarg,
01639                 NULL,
01640                 NULL,
01641                 FALSE,
01642                 CREATE_NO_WINDOW,
01643                 NULL,
01644                 pszInstallPath,
01645                 &SupInfo,
01646                 &ProcInfo
01647                );
01648 
01649   MyFiles(REMOVE);
01650   MyLinks(REMOVE);
01651   MyRegs(REMOVE);
01652   end(REMOVE_SUCCESS);
01653   }
01654 
01655 int WINAPI WinMain(HINSTANCE _this_instance,   
01656                    HINSTANCE prev_instance,
01657                    LPSTR commandline,
01658                    int win_state){
01659   char execvarg[SSLEN];
01660   STARTUPINFO SupInfo;
01661   PROCESS_INFORMATION ProcInfo;
01662   BOOL bCrP;
01663   DWORD Gle;
01664 
01665   SupInfo.cb = sizeof(SupInfo);
01666   SupInfo.lpReserved = NULL;
01667   SupInfo.lpDesktop = NULL;
01668   SupInfo.lpTitle = NULL;
01669   SupInfo.dwFlags = 0;
01670   SupInfo.cbReserved2 = 0;
01671   SupInfo.lpReserved2 = NULL;
01672   this_instance=_this_instance;
01673   progress_wait = 400;
01674   pszInstallPath = GetSBRegString("path");
01675 
01676   GetTempPath(SSLEN,string);
01677   temppath=brushup(string);
01678   // if the setup.exe is executed from the install path, then this is remove
01679   // in this case we do nothing but copy the executable and start it from the
01680   // temp directory in a new process. This will let uninstall remove the whole
01681   // directory, even the setup.exe
01682   // the only thing that remains is the copy of SETUP.EXE in the temp directory
01683   // That is scheduled to be deleted on the next reboot calling MoveFileEx
01684   if( pszInstallPath && ! strnicmp(_pgmptr,pszInstallPath,strlen(pszInstallPath)) ){
01685     sprintf(string,"%s\\setup.exe",temppath);
01686     CopyFile(_pgmptr,string,FALSE);
01687     sprintf(execvarg,"%s remove",string);
01688 
01689     bCrP =
01690     CreateProcess(string,
01691                   execvarg,
01692                   NULL,
01693                   NULL,
01694                   FALSE,
01695                   CREATE_NO_WINDOW,
01696                   NULL,
01697                   temppath,
01698                   &SupInfo,
01699                   &ProcInfo
01700                  );
01701 
01702     Gle = GetLastError();    
01703     exit(0);
01704     }
01705 
01706   logit("ScriptBasic installation was started");
01707 
01708   sprintf(logs,"--Commandline='%s'\n",commandline);
01709   logit(logs);
01710 
01711   /* write to log */
01712   sprintf(logs,"--Temppath: '%s'\n",temppath);
01713   logit(logs);
01714 
01715   /* get current path */
01716   GetCurrentDirectory(SSLEN,string);
01717   currentpath=brushup(string);
01718 
01719   /* write to log */
01720   sprintf(logs,"--Currentpath: '%s'\n",currentpath);
01721   logit(logs);
01722   
01723   
01724   /* 'parse' commandline */
01725   install=TRUE;
01726   if (!strcmp(commandline,"remove")) install=FALSE;
01727 
01728   // get the version that is already installed
01729   GetSBRegDW("major",&dwMajor);
01730   GetSBRegDW("minor",&dwMinor);
01731   GetSBRegDW("build",&dwBuild);
01732 
01733   sprintf(logs,"--Installed: ScriptBasic version is %d.%db%d\n",dwMajor,dwMinor,dwBuild);
01734   logit(logs);
01735 
01736   if( install )InstallScriptBasic();
01737   else RemoveScriptBasic();
01738 
01739   }

Generated on Sun Mar 12 23:56:31 2006 for ScriptBasic by  doxygen 1.4.6-NO