// Copyright distributed.net 1997-1999 - All Rights Reserved
// For use in distributed.net projects only.
// Any other distribution or use of this source violates copyright.
//
/*
**  This is the "prelude" module for the win32/win16 console client.
**  win32GUI shims are elsewhere.
**
**  "prelude" serves as a shim between WinMain() [in client.cpp] and
**  realmain() [also in client.cpp]
*/
//
// $Log: w32pre.cpp,v $
// Revision 1.6  1999/01/01 02:45:20  cramer
// Part 1 of 1999 Copyright updates...
//
// Revision 1.5  1998/12/16 07:13:38  cyp
// win16 changes. La, la join the dots.
//
// Revision 1.4  1998/12/01 00:24:38  cyp
// Created/combined various getversion functions in winGetVersion(). Created
// winInstallClient()/winDeinstallClient() [primarily for use with win16 but
// it execs w32Install/DeinstallService() if running on win32]
//
// Revision 1.3  1998/11/14 13:46:58  cyp
// Disabled previous instance check to allow multiple win16 instances (for
// modes).
//
// Revision 1.2  1998/10/19 13:21:15  cyp
// win16 changes
//
// Revision 1.1  1998/10/11 00:27:12  cyp
// Created.
//
//
//
#if (!defined(lint) && defined(__showids__))
const char *w32pre_cpp(void) {
return "@(#)$Id: w32pre.cpp,v 1.6 1999/01/01 02:45:20 cramer Exp $"; }
#endif

#include "baseincs.h" 

static struct 
{
  HINSTANCE hInstance;
  int nCmdShow;
  int argc;
  char **argv;
} prestatics = {NULL,0,0,NULL};


HINSTANCE winGetInstanceHandle(void)
{
  return prestatics.hInstance;
}

/* ----------------------------------- */

int winGetInstanceShowCmd(void)
{
  return prestatics.nCmdShow;
}

/* ----------------------------------- */

int winGetInstanceArgc(void)
{
  return prestatics.argc;
}

/* ----------------------------------- */

char **winGetInstanceArgv(void)
{
  return prestatics.argv;
}

/* ----------------------------------- */

long winGetVersion(void)
{
  static long ver = 0;

  if (ver == 0)
    {
    int versionmajor = 0, versionminor = 0;
    #if (CLIENT_OS == OS_WIN32)
      {
      OSVERSIONINFO osver;

      osver.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
      GetVersionEx(&osver);
      versionmajor = (int)osver.dwMajorVersion;
      versionminor = (int)osver.dwMinorVersion;
      if (VER_PLATFORM_WIN32_NT == osver.dwPlatformId)
        versionmajor += 20;
      }
    #else
      {
      DWORD dwVersion = GetVersion();
      versionmajor = LOBYTE(LOWORD(dwVersion));
      versionminor = HIBYTE(LOWORD(dwVersion));  
      //build number in (HIWORD(dwVersion) & 0x7FFF) in all but plain win3x
 
      if (versionmajor == 3 && versionminor >=95)
        {
        versionmajor = 4;
        versionminor = 1;
        }
      else if (dwVersion < 0x80000000) //winNT or win3x without win32s
        {
        if ( GetModuleHandle("KERNEL32") )
          versionmajor += 20;
        }
      }
    #endif

    ver = (((long)(versionmajor))*100)+versionminor;
    }
  return ver;
}

/* ----------------------------------- */

static char **parseCmdLine(HINSTANCE hInstance, LPSTR lpszCmdLine, int *argcP )
{
  static char *argv[64];
  static char argbuff[512];

  int argc=0, quotes;
  LPSTR start;
  char *aptr = &argbuff[0];

  argv[argc++] = &argbuff[0];
  GetModuleFileName(hInstance, argbuff, sizeof(argbuff));
  aptr = &argbuff[strlen(argbuff)+1];
  
  while (*lpszCmdLine)
    {
    quotes = 0;
    while (*lpszCmdLine==' ' || *lpszCmdLine=='\t')
      lpszCmdLine++;
    if (*lpszCmdLine == '\"' || *lpszCmdLine == '\'')
      quotes = *lpszCmdLine++;
    start = lpszCmdLine;
    while (*lpszCmdLine && ((quotes)?(*lpszCmdLine!=quotes):
                           (*lpszCmdLine!=' ' && *lpszCmdLine!='\t')))
      lpszCmdLine++;
    if (aptr + ((lpszCmdLine-start)+1) >= &argbuff[sizeof(argbuff)-1])
      break;
    argv[argc++] = aptr;
    while (start<lpszCmdLine)
      *aptr++ = *start++;
    *aptr++ = 0;
    if (quotes)
      lpszCmdLine++;
    if (argc+1 == (sizeof(argv)/sizeof(argv[1])))
      break;
    }
  argv[argc]=NULL;
  
  *argcP = argc;
  return argv;
}      
      
/* ----------------------------------- */

int winClientPrelude(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpszCmdLine, int nCmdShow, int (*realmain)(int, char **))
{
  int argc = (hPrevInstance != NULL); //use up argument
  char **argv;

  //if (hPrevInstance)
  //  {
  //  w32ConShowWindow(); //show window if not -runhidden
  //  return 0;
  //  }

  prestatics.hInstance = hInstance;
  prestatics.nCmdShow = nCmdShow;
  argv = parseCmdLine(hInstance, lpszCmdLine, &argc );

  if (argc==1 && winGetVersion() < 400) /* win16 */
    {
    if (FindWindow( "Progman", NULL )==NULL) /* started from load=/run= */
      {
      argv[argc++]="-hide";
      argv[argc]=NULL;
      }
    }

  prestatics.argc = argc;
  prestatics.argv = argv;

  #if (CLIENT_OS == OS_WIN32)
  if (winGetVersion() >= 2000) /* WinNT */
    {
    if (argc == 1) /* possibly old style NT service (no cmdline options) */
      {            
      if ( win32CliOldStyleInitializeService() == 0 ) /* started ok */
        return 0;  /* service started (or errors handled) so quit here */
      }
    if (argc >= 2 && strcmp( argv[1], "-svcrun" ) == 0) 
      {                                     
      if ( win32CliInitializeService(argc,argv) == 0) /* started ok */
        return 0;  /* service started so quit here */
      /*inappropriate "-svcrun". fall through and let the cmdline parser puke*/
      }
    } /* if (VER_PLATFORM_WIN32_NT == osver.dwPlatformId) */
  #endif //#if (CLIENT_OS == OS_WIN32)   

  return (*realmain)( argc, argv );
}


/* ---------------------------------------------------- */

static int __winInstallDeinstallClient( int doinstall, int quietly )
{
  char inibuffer[1024];
  const char *boxmsg = NULL;
  char *fullpath = NULL;
  unsigned int maxlen, pathlen = 0;
  int retcode;

  if (winGetInstanceArgv() != NULL)
    fullpath = winGetInstanceArgv()[0];

  if (fullpath == NULL)
    {
    boxmsg = "Unable to obtain full path to exe name.";
    retcode = -1;
    }
  else if (winGetVersion() >= 400)
    {
    boxmsg = "Invalid windows version for Win16 -install or -deinstall";
    retcode = -1;
    #if (CLIENT_OS == OS_WIN32)
    return ((doinstall)?(win32CliInstallService(quietly)):
                        (win32CliUninstallService(quietly)));
    #endif
    }
  else if ((pathlen = strlen(fullpath)) >= 127)
    {
    boxmsg = "Path to executable is too long to -install or -deinstall";
    retcode = -1;
    }
  else
    {  
    char *option = "run";
    char *p = NULL;
    strlwr(fullpath);

    if (( GetProfileString("windows", option, "", 
             inibuffer, sizeof(inibuffer)-1)) != 0)
      {
      strlwr( inibuffer );
      p = strstr( inibuffer, fullpath );
      }
    if (p == NULL && ( GetProfileString("windows", "load", "", 
             inibuffer, sizeof(inibuffer)-1)) != 0)
      {
      option = "load";
      strlwr( inibuffer );
      p = strstr( inibuffer, fullpath );
      }
    if (p == NULL)
      {
      boxmsg = "This client is not installed. Cannot uninstall.";
      retcode = ((doinstall)?(0):(-1));
      }
    else
      {
      GetProfileString("windows", option, "", inibuffer, sizeof(inibuffer)-1);
      char *q=p+pathlen;
      while (*q && isspace(*q))
        q++;
      memmove( p, q, (q-p) );
      if ( WriteProfileString( "windows", option, inibuffer ))
        {
        boxmsg = "The RC5DES client has been successfully uninstalled.";
        retcode = 0;
        }
      else
        {
        if (doinstall)
          boxmsg = "Unable to deinstall before -install";
        else
          boxmsg = "Unable to update WIN.INI for -uninstall.";
        retcode = -1;
        }
      }
      
    if (doinstall && retcode == 0)
      {
      maxlen = 127-(pathlen+2);
    
      option = "run";
      if (GetProfileString("windows", option, "", 
        inibuffer, sizeof(inibuffer)-1) > maxlen)
        {
        option = "load";
        if (GetProfileString("windows", option, "", 
            inibuffer, sizeof(inibuffer)-1) > maxlen)
          {
          boxmsg = "Insufficient space in WIN.INI load/run "
                   "entries to -install";
          retcode = -1;
          }
        }
      if (retcode == 0)
        {
        pathlen = strlen( inibuffer );
        while ((pathlen > 0) && isspace(inibuffer[pathlen-1]))
          inibuffer[--pathlen]=0;
        while ((pathlen > 0) && isspace(inibuffer[0]))
          memmove((void *)(&inibuffer[0]),(void *)(&inibuffer[1]),--pathlen);
        if (inibuffer[0])
          strcat( inibuffer, " ");
        strcat( inibuffer, fullpath );
        if ( WriteProfileString( "windows", option, inibuffer ))
          {
          boxmsg = "The RC5DES client has been installed successfully.";
          retcode = 0;
          }
        else
          {
          boxmsg = "Unable to update WIN.INI for -install.";
          retcode = -1;
          }
        }
      }
    }
    
  if (quietly==0 && boxmsg!=NULL)
    {
    MessageBox( NULL, boxmsg, "distributed.net RC5DES client", 
      MB_OK|MB_TASKMODAL|((retcode==0)?(MB_ICONINFORMATION):(MB_ICONHAND)) );
    }
  return retcode;
}  

/* ---------------------------------------------------- */

int winInstallClient(int quietly) 
{return __winInstallDeinstallClient( 1, quietly ); }
int winUninstallClient(int quietly) 
{return __winInstallDeinstallClient( 0, quietly ); }

/* ---------------------------------------------------- */
