#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>

void CreateRoot(char *buf)
{
   char *s = strrchr(buf,'\\') ;
   int rv ;
   if (s && s != buf && *(s-1) != ':') {
        *s = 0 ;
        CreateRoot(buf) ;
        *s = '\\' ;
   }
   if (!CreateDirectory(buf,0) && GetLastError()!= ERROR_ALREADY_EXISTS) {
      printf("%d %s\n",GetLastError(),buf) ;
        fatal("Cannot Create Directory Tree") ;
   }
}
void MakeDir(char *dir, char *ext)
{
   char buf[256] ;
   sprintf(buf,"%s%s",dir,ext) ;
   if (!CreateDirectory(buf,0)) {
      if (GetLastError() != ERROR_ALREADY_EXISTS) 
        fatal("Cannot create directory tree") ;
   }
}
void DoUnZip(char *dir, char *ext, char *name)
{
   char buf[256] ;
   sprintf(buf,"%s%s",dir,ext) ;
   if (unzip(name,buf))
      fatal("Cannot extract files") ;
}
void Register(char *path)
{
   HKEY key,key2 ;
   DWORD disp ;
   if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,"Software\\LadSoft\\CC386",0,0,
         0,KEY_ALL_ACCESS,0,&key,&disp) == ERROR_SUCCESS) {
      RegSetValueEx(key,"InstallPath",0,REG_SZ,path,strlen(path)) ;
      RegSetValueEx(key,"Installed",0,REG_SZ,"1",1) ;
      if (RegCreateKeyEx(key,"CCIDE",0,0,
            0,KEY_ALL_ACCESS,0,&key2,&disp) == ERROR_SUCCESS) {
         path[strlen(path)-1] = 0 ; // get rid of final slash
         RegSetValueEx(key2,"InstallPath",0,REG_SZ,path,strlen(path)) ;
         RegCloseKey(key2) ;
      }

      RegCloseKey(key) ;
   }

}
int IsInstalled(char *path)
{
   HKEY key ;
   int rv = 0 ;
   int type ;
   int size = 256 ;
   DWORD disp ;
   if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\LadSoft\\CC386",0,
         KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) {
      if (RegQueryValueEx(key,"InstallPath",0,&type,path,&size) == ERROR_SUCCESS)
            rv = 1 ;
      RegCloseKey(key) ;
   }
   return rv ;
}
void WriteCfg(char *path,char *file, char *fmt, ...)
{
  char buf[20000],ipath[256] ;
  FILE *fil ;
  va_list argptr;

  va_start( argptr, fmt);
  vsprintf(buf, fmt, argptr);
  va_end(argptr);
  sprintf(ipath,"%s%s",path,file) ;
  fil = fopen(ipath,"w") ;
  if (!fil)
     fatal("Cannot write config file") ;
   fwrite(buf,strlen(buf),1,fil) ;
   fclose(fil) ;
}
int IsNT(void)
{
   HANDLE privtok ;
   if (!OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS, &privtok)) {
      if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
         return FALSE ;
      printf("%d",GetLastError()) ;
   } else
      CloseHandle(privtok) ;
   return TRUE ;
}
void AddToDosPath(char *path)
{
   if (!IsNT()) {
      char buf[256] ;
      printf("Would you like to add the path to autoexec.bat? [y/n]") ;
      scanf("%s",buf) ;
      if (buf[0] == 'Y' || buf[0] == 'y') {
         FILE *fil = fopen("C:\\autoexec.bat","a") ;
         if (!fil)
            fatal("Could not locate autoexec.bat") ;
         fprintf(fil,"\nPATH=%sbin;%%PATH%%\n",path) ;
         fclose(fil) ;
      }
   }
}
void main()
{
   char buf[256], installpath[256];
   int i;

   if (IsInstalled(installpath)) {
      printf("CC386 is already installed.  Would you like to reinstall? [y/n]") ;
      fgets(buf,256,stdin) ;
      if (buf[0] == 'y' || buf[0] == 'Y')
         RemoveFromPath(installpath) ;
      else
         exit(0) ;
   }
   printf("Enter installation path: ") ;
   fgets(installpath,256,stdin) ;

   if (installpath[strlen(installpath)-1] == '\n') 
      installpath[strlen(installpath)-1] = 0 ;

   if (installpath[strlen(installpath)-1] != '\\')
      strcat(installpath,"\\") ;

   for (i=0; i < strlen(installpath) ; i++ )
      installpath[i] = toupper(installpath[i]) ;

   printf("Creating directory tree...\n") ;
   CreateRoot(installpath) ;
   MakeDir(installpath,"bin") ;
   MakeDir(installpath,"examples") ;
   MakeDir(installpath,"examples\\dos") ;
   MakeDir(installpath,"examples\\windows") ;
   MakeDir(installpath,"lib") ;
   MakeDir(installpath,"lib\\startup") ;
   MakeDir(installpath,"include") ;
   MakeDir(installpath,"include\\win32") ;
   MakeDir(installpath,"espanol") ;
   MakeDir(installpath,"english") ;

   printf("Copying files...\n") ;
   DoUnZip(installpath,"","root.zip") ;
   DoUnZip(installpath,"bin","bin.zip") ;
   DoUnZip(installpath,"examples","examples.zip") ;
   DoUnZip(installpath,"examples\\dos","dosexam.zip") ;
   DoUnZip(installpath,"examples\\windows","winexam.zip") ;
   DoUnZip(installpath,"lib","lib.zip") ;
   DoUnZip(installpath,"lib\\startup","libs.zip") ;
   DoUnZip(installpath,"include","include.zip") ;
   DoUnZip(installpath,"include\\win32","includew.zip") ;
   DoUnZip(installpath,"espanol","espanol.zip") ;
   DoUnZip(installpath,"english","english.zip") ;

   printf("Configuring...\n") ;
   WriteCfg(installpath, "bin\\CC386.CFG","-I%sinclude\n",installpath) ;
   WriteCfg(installpath, "bin\\VALX.CFG","-L:(%slib)\n",installpath) ;
   WriteCfg(installpath, "bin\\cl386.CFG","-I%sINCLUDE -L%sLIB"
            " -e /NASM /VALX /C+d\n",installpath,installpath) ;
   WriteCfg(installpath, "bin\\mk386.CFG"," -I%sINCLUDE -L%sLIB"
            " -$A=NASM -$L=VALX -$M=IMAKE\n", installpath, installpath) ;
   WriteCfg(installpath,"bin\\build.bat","@echo off\n"
            " cc386 /A- %%1.c\n"
            " if not errorlevel = 0 goto exit\n"
            " valx -nci -pe -32 -con c0xwin.obj %%1.obj,%%1,%%1,clwin.lib climp.lib,,\n"
            ":exit\n") ;

   Register(installpath) ;
   printf("Adding to path...\n") ;
   AddToPath(installpath) ;
   AddToDosPath(installpath) ;
   printf("Installation completed successfully\n\n") ;

   printf("Installation requires a reboot.\n"
          "Would you like to reboot now? [y/n]") ;
   scanf("%s",buf) ;
   if (buf[0] == 'Y' || buf[0] == 'y') {
      PROCESS_INFORMATION pi ;
      STARTUPINFO si ;
      memset(&si,0,sizeof(si)) ;
      si.cb = sizeof(si) ;
      CreateProcess(0,"wreboot.exe",0,0,FALSE,0,0,0,&si,&pi) ;
   }
}