Index: src/blob.c
==================================================================
--- src/blob.c
+++ src/blob.c
@@ -130,11 +130,11 @@
 }
 
 /*
 ** A reallocation function that assumes that aData came from malloc().
 ** This function attempts to resize the buffer of the blob to hold
-** newSize bytes.  
+** newSize bytes.
 **
 ** No attempt is made to recover from an out-of-memory error.
 ** If an OOM error occurs, an error message is printed on stderr
 ** and the program exits.
 */
@@ -368,11 +368,11 @@
      ((B)->nUsed==sizeof(S)-1 && memcmp((B)->aData,S,sizeof(S)-1)==0)
 #endif
 
 
 /*
-** Attempt to resize a blob so that its internal buffer is 
+** Attempt to resize a blob so that its internal buffer is
 ** nByte in size.  The blob is truncated if necessary.
 */
 void blob_resize(Blob *pBlob, unsigned int newSize){
   pBlob->xRealloc(pBlob, newSize+1);
   pBlob->nUsed = newSize;
@@ -453,11 +453,11 @@
 int blob_tell(Blob *p){
   return p->iCursor;
 }
 
 /*
-** Extract a single line of text from pFrom beginning at the current 
+** Extract a single line of text from pFrom beginning at the current
 ** cursor location and use that line of text to initialize pTo.
 ** pTo will include the terminating \n.  Return the number of bytes
 ** in the line including the \n at the end.  0 is returned at
 ** end-of-file.
 **
@@ -669,11 +669,11 @@
 void blob_vappendf(Blob *pBlob, const char *zFormat, va_list ap){
   vxprintf(pBlob, zFormat, ap);
 }
 
 /*
-** Initalize a blob to the data on an input channel.  Return 
+** Initalize a blob to the data on an input channel.  Return
 ** the number of bytes read into the blob.  Any prior content
 ** of the blob is discarded, not freed.
 */
 int blob_read_from_channel(Blob *pBlob, FILE *in, int nToRead){
   size_t n;
@@ -767,22 +767,16 @@
 int blob_write_to_file(Blob *pBlob, const char *zFilename){
   FILE *out;
   int wrote;
 
   if( zFilename[0]==0 || (zFilename[0]=='-' && zFilename[1]==0) ){
-    int n;
+    int n = blob_size(pBlob);
 #if defined(_WIN32)
-    if( _isatty(fileno(stdout)) ){
-      char *z;
-      z = fossil_utf8_to_console(blob_str(pBlob));
-      n = strlen(z);
-      fwrite(z, 1, n, stdout);
-      free(z);
+    if( fossil_utf8_to_console(blob_buffer(pBlob), n, 0) >= 0 ){
       return n;
     }
 #endif
-    n = blob_size(pBlob);
     fwrite(blob_buffer(pBlob), 1, n, stdout);
     return n;
   }else{
     int i, nName;
     char *zName, zBuf[1000];
@@ -833,12 +827,12 @@
   return wrote;
 }
 
 /*
 ** Compress a blob pIn.  Store the result in pOut.  It is ok for pIn and
-** pOut to be the same blob. 
-** 
+** pOut to be the same blob.
+**
 ** pOut must either be the same as pIn or else uninitialized.
 */
 void blob_compress(Blob *pIn, Blob *pOut){
   unsigned int nIn = blob_size(pIn);
   unsigned int nOut = 13 + nIn + (nIn+999)/1000;
@@ -871,13 +865,13 @@
   blob_compress(&f, &f);
   blob_write_to_file(&f, g.argv[3]);
 }
 
 /*
-** Compress the concatenation of a blobs pIn1 and pIn2.  Store the result 
-** in pOut. 
-** 
+** Compress the concatenation of a blobs pIn1 and pIn2.  Store the result
+** in pOut.
+**
 ** pOut must be either uninitialized or must be the same as either pIn1 or
 ** pIn2.
 */
 void blob_compress2(Blob *pIn1, Blob *pIn2, Blob *pOut){
   unsigned int nIn = blob_size(pIn1) + blob_size(pIn2);
@@ -944,11 +938,11 @@
   inBuf = (unsigned char*)blob_buffer(pIn);
   nOut = (inBuf[0]<<24) + (inBuf[1]<<16) + (inBuf[2]<<8) + inBuf[3];
   blob_zero(&temp);
   blob_resize(&temp, nOut+1);
   nOut2 = (long int)nOut;
-  rc = uncompress((unsigned char*)blob_buffer(&temp), &nOut2, 
+  rc = uncompress((unsigned char*)blob_buffer(&temp), &nOut2,
                   &inBuf[4], nIn - 4);
   if( rc!=Z_OK ){
     blob_reset(&temp);
     return 1;
   }
@@ -1062,11 +1056,11 @@
 **
 ** Returns the number of bytes read/copied, which may be less than
 ** nLen (if end-of-blob is encountered).
 **
 ** Updates pIn's cursor.
-** 
+**
 ** Returns 0 if pIn contains no data.
 */
 unsigned int blob_read(Blob *pIn, void * pDest, unsigned int nLen ){
   if( !pIn->aData || (pIn->iCursor >= pIn->nUsed) ){
     return 0;

Index: src/file.c
==================================================================
--- src/file.c
+++ src/file.c
@@ -114,11 +114,11 @@
 
 /*
 ** Same as file_size(), but takes into account symlinks.
 */
 i64 file_wd_size(const char *zFilename){
-  return getStat(zFilename, 1) ? -1 : fileStat.st_size;  
+  return getStat(zFilename, 1) ? -1 : fileStat.st_size;
 }
 
 /*
 ** Return the modification time for a file.  Return -1 if the file
 ** does not exist.  If zFilename is NULL return the size of the most
@@ -134,11 +134,11 @@
 i64 file_wd_mtime(const char *zFilename){
   return getStat(zFilename, 1) ? -1 : fileStat.st_mtime;
 }
 
 /*
-** Return TRUE if the named file is an ordinary file or symlink 
+** Return TRUE if the named file is an ordinary file or symlink
 ** and symlinks are allowed.
 ** Return false for directories, devices, fifos, etc.
 */
 int file_wd_isfile_or_link(const char *zFilename){
   return getStat(zFilename, 1) ? 0 : S_ISREG(fileStat.st_mode) ||
@@ -191,14 +191,14 @@
       }
     }
     if( zName!=zBuf ) free(zName);
 
     if( symlink(zTargetFile, zName)!=0 ){
-      fossil_fatal_recursive("unable to create symlink \"%s\"", zName);      
+      fossil_fatal_recursive("unable to create symlink \"%s\"", zName);
     }
   }else
-#endif 
+#endif
   {
     Blob content;
     blob_set(&content, zTargetFile);
     blob_write_to_file(&content, zLinkFile);
     blob_reset(&content);
@@ -230,11 +230,11 @@
   if( S_ISREG(fileStat.st_mode) && ((S_IXUSR)&fileStat.st_mode)!=0 )
     return PERM_EXE;
   else
     return PERM_REG;
 #else
-  if( S_ISREG(fileStat.st_mode) && 
+  if( S_ISREG(fileStat.st_mode) &&
       ((S_IXUSR|S_IXGRP|S_IXOTH)&fileStat.st_mode)!=0 )
     return PERM_EXE;
   else if( g.allowSymlinks && S_ISLNK(fileStat.st_mode) )
     return PERM_LNK;
   else
@@ -405,11 +405,11 @@
 #endif
 }
 
 /*
 ** Create the directory named in the argument, if it does not already
-** exist.  If forceFlag is 1, delete any prior non-directory object 
+** exist.  If forceFlag is 1, delete any prior non-directory object
 ** with the same name.
 **
 ** Return the number of errors.
 */
 int file_mkdir(const char *zName, int forceFlag){
@@ -719,11 +719,11 @@
     }
   }
   return 1;
 }
 
-/* 
+/*
 ** Return a pointer to the first character in a pathname past the
 ** drive letter.  This routine is a no-op on unix.
 */
 char *file_without_drive_letter(char *zIn){
 #ifdef _WIN32
@@ -947,19 +947,19 @@
 
   azDirs[1] = fossil_getenv("TEMP");
   azDirs[2] = fossil_getenv("TMP");
 #endif
 
-  
+
   for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){
     if( azDirs[i]==0 ) continue;
     if( !file_isdir(azDirs[i]) ) continue;
     zDir = azDirs[i];
     break;
   }
 
-  /* Check that the output buffer is large enough for the temporary file 
+  /* Check that the output buffer is large enough for the temporary file
   ** name. If it is not, return SQLITE_ERROR.
   */
   if( (strlen(zDir) + 17) >= (size_t)nBuf ){
     fossil_fatal("insufficient space for temporary filename");
   }
@@ -1035,21 +1035,21 @@
 ** Since everything is always UTF8 on unix, these routines are no-ops
 ** there.
 */
 
 /*
-** Translate MBCS to UTF8.  Return a pointer to the translated text.  
+** Translate MBCS to UTF8.  Return a pointer to the translated text.
 ** Call fossil_mbcs_free() to deallocate any memory used to store the
 ** returned pointer when done.
 */
 char *fossil_mbcs_to_utf8(const char *zMbcs){
 #ifdef _WIN32
   extern char *sqlite3_win32_mbcs_to_utf8(const char*);
   return sqlite3_win32_mbcs_to_utf8(zMbcs);
 #else
   return (char*)zMbcs;  /* No-op on unix */
-#endif  
+#endif
 }
 
 /*
 ** Translate Unicode to UTF8.  Return a pointer to the translated text.
 ** Call fossil_mbcs_free() to deallocate any memory used to store the
@@ -1078,11 +1078,11 @@
 #ifdef _WIN32
   extern char *sqlite3_win32_utf8_to_mbcs(const char*);
   return sqlite3_win32_utf8_to_mbcs(zUtf8);
 #else
   return (char*)zUtf8;  /* No-op on unix */
-#endif  
+#endif
 }
 
 /*
 ** Translate UTF8 to unicode for use in system calls.  Return a pointer to the
 ** translated text..  Call fossil_mbcs_free() to deallocate any memory
@@ -1116,48 +1116,71 @@
 #endif
   return zValue;
 }
 
 /*
-** Translate UTF8 to MBCS for display on the console.  Return a pointer to the
-** translated text..  Call fossil_mbcs_free() to deallocate any memory
-** used to store the returned pointer when done.
+** Display UTF8 on the console.  Return the number of
+** Characters written. If stdout or stderr is redirected
+** to a file, -1 is returned and nothing is written
+** to the console.
 */
-char *fossil_utf8_to_console(const char *zUtf8){
+int fossil_utf8_to_console(const char *zUtf8, int nByte, int toStdErr){
 #ifdef _WIN32
-  int nChar, nByte;
-  WCHAR *zUnicode;   /* Unicode version of zUtf8 */
+  int nChar;
+  wchar_t *zUnicode; /* Unicode version of zUtf8 */
+#ifdef UNICODE
+  DWORD dummy;
+#else
   char *zConsole;    /* Console version of zUtf8 */
   int codepage;      /* Console code page */
+#endif
+
+  static int istty[2] = { -1, -1 };
+  if( istty[toStdErr] == -1 ){
+    istty[toStdErr] = _isatty(toStdErr + 1) != 0;
+  }
+  if( !istty[toStdErr] ){
+    /* stdout/stderr is not a console. */
+    return -1;
+  }
 
-  nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, NULL, 0);
-  zUnicode = malloc( nChar*sizeof(zUnicode[0]) );
+  nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, nByte, NULL, 0);
+  zUnicode = malloc( (nChar + 1) *sizeof(zUnicode[0]) );
   if( zUnicode==0 ){
     return 0;
   }
-  nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nChar);
+  nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, nByte, zUnicode, nChar);
   if( nChar==0 ){
     free(zUnicode);
     return 0;
   }
+  zUnicode[nChar] = '\0';
+#ifdef UNICODE
+  WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE - toStdErr), zUnicode, nChar, &dummy, 0);
+#else /* !UNICODE */
   codepage = GetConsoleCP();
-  nByte = WideCharToMultiByte(codepage, 0, zUnicode, -1, 0, 0, 0, 0);
-  zConsole = malloc( nByte );
+  nByte = WideCharToMultiByte(codepage, 0, zUnicode, nChar, 0, 0, 0, 0);
+  zConsole = malloc( nByte + 1);
   if( zConsole==0 ){
     free(zUnicode);
     return 0;
   }
-  nByte = WideCharToMultiByte(codepage, 0, zUnicode, -1, zConsole, nByte, 0, 0);
+  nByte = WideCharToMultiByte(codepage, 0, zUnicode, nChar, zConsole, nByte, 0, 0);
+  zConsole[nByte] = '\0';
   free(zUnicode);
   if( nByte == 0 ){
     free(zConsole);
     zConsole = 0;
+    return 0;
   }
-  return zConsole;
+  fwrite(zConsole, 1, nByte, toStdErr ? stderr : stdout);
+  fflush(toStdErr ? stderr : stdout);
+#endif /* UNICODE */
+  return nChar;
 #else
-  return (char*)zUtf8;  /* No-op on unix */
-#endif  
+  return -1;  /* No-op on unix */
+#endif
 }
 
 /*
 ** Translate MBCS to UTF8.  Return a pointer.  Call fossil_mbcs_free()
 ** to deallocate any memory used to store the returned pointer when done.
@@ -1166,11 +1189,11 @@
 #ifdef _WIN32
   extern void sqlite3_free(void*);
   sqlite3_free(zOld);
 #else
   /* No-op on unix */
-#endif  
+#endif
 }
 
 /*
 ** Like fopen() but always takes a UTF8 argument.
 */

Index: src/main.c
==================================================================
--- src/main.c
+++ src/main.c
@@ -157,11 +157,11 @@
   char *urlPasswd;        /* Password for http: */
   char *urlCanonical;     /* Canonical representation of the URL */
   char *urlProxyAuth;     /* Proxy-Authorizer: string */
   char *urlFossil;        /* The path of the ?fossil=path suffix on ssh: */
   int dontKeepUrl;        /* Do not persist the URL */
-  
+
   const char *zLogin;     /* Login name.  "" if not logged in. */
   const char *zSSLIdentity;  /* Value of --ssl-identity option, filename of SSL client identity */
   int useLocalauth;       /* No login required if from 127.0.0.1 */
   int noPswd;             /* Logged in without password (on 127.0.0.1) */
   int userUid;            /* Integer user id */
@@ -168,11 +168,11 @@
 
   /* Information used to populate the RCVFROM table */
   int rcvid;              /* The rcvid.  0 if not yet defined. */
   char *zIpAddr;          /* The remote IP address */
   char *zNonce;           /* The nonce used for login */
-  
+
   /* permissions used by the server */
   struct FossilUserPerms perm;
 
 #ifdef FOSSIL_ENABLE_TCL
   /* all Tcl related context necessary for integration */
@@ -195,11 +195,11 @@
   const char *azAuxName[MX_AUX]; /* Name of each aux() or option() value */
   char *azAuxParam[MX_AUX];      /* Param of each aux() or option() value */
   const char *azAuxVal[MX_AUX];  /* Value of each aux() or option() value */
   const char **azAuxOpt[MX_AUX]; /* Options of each option() value */
   int anAuxCols[MX_AUX];         /* Number of columns for option() values */
-  
+
   int allowSymlinks;             /* Cached "allow-symlinks" option */
 
 #ifdef FOSSIL_ENABLE_JSON
   struct FossilJsonBits {
     int isJsonMode;            /* True if running in JSON mode, else
@@ -262,11 +262,11 @@
 #endif
 
 Global g;
 
 /*
-** The table of web pages supported by this application is generated 
+** The table of web pages supported by this application is generated
 ** automatically by the "mkindex" program and written into a file
 ** named "page_index.h".  We include that file here to get access
 ** to the table.
 */
 #include "page_index.h"
@@ -330,29 +330,146 @@
   if(g.db){
     db_close(0);
   }
 }
 
+#if defined(_WIN32)
 /*
-** Convert all arguments from mbcs to UTF-8. Then
+** Parse the command-line arguments passed to windows.  We do this
+** ourselves to work around bugs in the command-line parsing of MinGW.
+** It is possible (in theory) to only use this routine when compiling
+** with MinGW and to use built-in command-line parsing for MSVC and
+** MinGW-64.  However, the code is here, it is efficient, and works, and
+** by using it in all cases we do a better job of testing it.  If you suspect
+** a bug in this code, test your theory by invoking "fossil test-echo".
+**
+** This routine is copied from TCL with some reformatting.
+** The original comment text follows:
+**
+** Parse the Windows command line string into argc/argv. Done here
+** because we don't trust the builtin argument parser in crt0. Windows
+** applications are responsible for breaking their command line into
+** arguments.
+**
+** 2N backslashes + quote -> N backslashes + begin quoted string
+** 2N + 1 backslashes + quote -> literal
+** N backslashes + non-quote -> literal
+** quote + quote in a quoted string -> single quote
+** quote + quote not in quoted string -> empty string
+** quote -> begin quoted string
+**
+** Results:
+** Fills argcPtr with the number of arguments and argvPtr with the array
+** of arguments.
+*/
+#include <tchar.h>
+#define tchar_isspace(X)  ((X)==TEXT(' ') || (X)==TEXT('\t'))
+static void parse_windows_command_line(
+  int *argcPtr,   /* Filled with number of argument strings. */
+  void *argvPtr   /* Filled with argument strings (malloc'd). */
+){
+  TCHAR *cmdLine, *p, *arg, *argSpace;
+  TCHAR **argv;
+  int argc, size, inquote, copy, slashes;
+
+  cmdLine = GetCommandLine();
+
+  /*
+  ** Precompute an overly pessimistic guess at the number of arguments in
+  ** the command line by counting non-space spans.
+  */
+  size = 2;
+  for(p=cmdLine; *p!=TEXT('\0'); p++){
+    if( tchar_isspace(*p) ){
+      size++;
+      while( tchar_isspace(*p) ){
+        p++;
+      }
+      if( *p==TEXT('\0') ){
+        break;
+      }
+    }
+  }
+
+  argSpace = fossil_malloc(size * sizeof(char*)
+    + (_tcslen(cmdLine) * sizeof(TCHAR)) + sizeof(TCHAR));
+  argv = (TCHAR**)argSpace;
+  argSpace += size*(sizeof(char*)/sizeof(TCHAR));
+  size--;
+
+  p = cmdLine;
+  for(argc=0; argc<size; argc++){
+    argv[argc] = arg = argSpace;
+    while( tchar_isspace(*p) ){
+      p++;
+    }
+    if (*p == TEXT('\0')) {
+      break;
+    }
+    inquote = 0;
+    slashes = 0;
+    while(1){
+      copy = 1;
+      while( *p==TEXT('\\') ){
+        slashes++;
+        p++;
+      }
+      if( *p==TEXT('"') ){
+        if( (slashes&1)==0 ){
+          copy = 0;
+          if( inquote && p[1]==TEXT('"') ){
+            p++;
+            copy = 1;
+          }else{
+            inquote = !inquote;
+          }
+        }
+        slashes >>= 1;
+      }
+      while( slashes ){
+        *arg = TEXT('\\');
+        arg++;
+        slashes--;
+      }
+      if( *p==TEXT('\0') || (!inquote && tchar_isspace(*p)) ){
+        break;
+      }
+      if( copy!=0 ){
+        *arg = *p;
+        arg++;
+      }
+      p++;
+    }
+    *arg = '\0';
+    argSpace = arg + 1;
+  }
+  argv[argc] = NULL;
+  *argcPtr = argc;
+  *((TCHAR ***)argvPtr) = argv;
+}
+#endif /* defined(_WIN32) */
+
+
+/*
+** Convert all arguments from mbcs (or unicode) to UTF-8. Then
 ** search g.argv for arguments "--args FILENAME". If found, then
 ** (1) remove the two arguments from g.argv
 ** (2) Read the file FILENAME
 ** (3) Use the contents of FILE to replace the two removed arguments:
 **     (a) Ignore blank lines in the file
 **     (b) Each non-empty line of the file is an argument, except
 **     (c) If the line begins with "-" and contains a space, it is broken
 **         into two arguments at the space.
 */
-static void expand_args_option(int argc, char **argv){
+static void expand_args_option(int argc, void *argv){
   Blob file = empty_blob;   /* Content of the file */
   Blob line = empty_blob;   /* One line of the file */
   unsigned int nLine;       /* Number of lines in the file*/
   unsigned int i, j, k;     /* Loop counters */
   int n;                    /* Number of bytes in one line */
-  char *z;            /* General use string pointer */
-  char **newArgv;     /* New expanded g.argv under construction */
+  char *z;                  /* General use string pointer */
+  char **newArgv;           /* New expanded g.argv under construction */
   char const * zFileName;   /* input file name */
   FILE * zInFile;           /* input FILE */
   int foundBom = -1;        /* -1= not searched yet, 0 = no; 1=yes */
 #ifdef _WIN32
   wchar_t buf[MAX_PATH];
@@ -359,13 +476,18 @@
 #endif
 
   g.argc = argc;
   g.argv = argv;
 #ifdef _WIN32
+  parse_windows_command_line(&g.argc, &g.argv);
   GetModuleFileNameW(NULL, buf, MAX_PATH);
   g.argv[0] = fossil_unicode_to_utf8(buf);
+#ifdef UNICODE
+  for(i=1; i<g.argc; i++) g.argv[i] = fossil_unicode_to_utf8(g.argv[i]);
+#else
   for(i=1; i<g.argc; i++) g.argv[i] = fossil_mbcs_to_utf8(g.argv[i]);
+#endif
 #endif
   for(i=1; i<g.argc-1; i++){
     z = g.argv[i];
     if( z[0]!='-' ) continue;
     z++;
@@ -390,21 +512,21 @@
   }
   z = blob_str(&file);
   for(k=0, nLine=1; z[k]; k++) if( z[k]=='\n' ) nLine++;
   newArgv = fossil_malloc( sizeof(char*)*(g.argc + nLine*2) );
   for(j=0; j<i; j++) newArgv[j] = g.argv[j];
-  
+
   blob_rewind(&file);
   while( (n = blob_line(&file, &line))>0 ){
     if( n<=1 ) continue;
     z = blob_buffer(&line);
     z[n-1] = 0;
     if (foundBom == -1) {
       static const char bom[] = { 0xEF, 0xBB, 0xBF };
       foundBom = memcmp(z, bom, 3)==0;
       if( foundBom ) {
-    	  z += 3; n -= 3;
+        z += 3; n -= 3;
       }
     }
     if((n>1) && ('\r'==z[n-2])){
       if(n==2) continue /*empty line*/;
       z[n-2] = 0;
@@ -430,11 +552,16 @@
 }
 
 /*
 ** This procedure runs first.
 */
-int main(int argc, char **argv){
+#if defined(_WIN32) && defined(UNICODE)
+int wmain(int argc, wchar_t **argv)
+#else
+int main(int argc, char **argv)
+#endif
+{
   const char *zCmdName = "unknown";
   int idx;
   int rc;
 
   sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0);
@@ -726,12 +853,12 @@
 #else
   /* On unix, evaluate the command directly.
   */
   if( g.fSystemTrace ) fprintf(stderr, "SYSTEM: %s\n", zOrigCmd);
   rc = system(zOrigCmd);
-#endif 
-  return rc; 
+#endif
+  return rc;
 }
 
 /*
 ** Turn off any NL to CRNL translation on the stream given as an
 ** argument.  This is a no-op on unix but is necessary on windows.
@@ -1194,11 +1321,11 @@
 **  * Environment variables are set up according to the CGI standard.
 **
 ** If the repository is known, it has already been opened.  If unknown,
 ** then g.zRepositoryName holds the directory that contains the repository
 ** and the actual repository is taken from the first element of PATH_INFO.
-** 
+**
 ** Process the webpage specified by the PATH_INFO or REQUEST_URI
 ** environment variable.
 */
 static void process_one_web_page(const char *zNotFound){
   const char *zPathInfo;
@@ -1267,11 +1394,11 @@
     cgi_replace_parameter("PATH_INFO", &zPathInfo[i+1]);
     zPathInfo += i;
     cgi_replace_parameter("SCRIPT_NAME", zNewScript);
     db_open_repository(zRepo);
     if( g.fHttpTrace ){
-      fprintf(stderr, 
+      fprintf(stderr,
           "# repository: [%s]\n"
           "# new PATH_INFO = [%s]\n"
           "# new SCRIPT_NAME = [%s]\n",
           zRepo, zPathInfo, zNewScript);
     }
@@ -1282,11 +1409,11 @@
   */
   if( g.zContentType && memcmp(g.zContentType, "application/x-fossil", 20)==0 ){
     zPathInfo = "/xfer";
   }
   set_base_url();
-  if( zPathInfo==0 || zPathInfo[0]==0 
+  if( zPathInfo==0 || zPathInfo[0]==0
       || (zPathInfo[0]=='/' && zPathInfo[1]==0) ){
 #ifdef FOSSIL_ENABLE_JSON
     if(g.json.isJsonMode){
       json_err(FSL_JSON_E_RESOURCE_NOT_FOUND,NULL,1);
       fossil_exit(0);
@@ -1312,11 +1439,11 @@
       ** that accepts the login credentials of the current repository.  A
       ** subrepository is identified by a CONFIG table entry "subrepo:NAME"
       ** where NAME is the first component of the path.  The value of the
       ** the CONFIG entries is the string "USER:FILENAME" where USER is the
       ** USER name to log in as in the subrepository and FILENAME is the
-      ** repository filename. 
+      ** repository filename.
       */
       zAltRepo = db_text(0, "SELECT value FROM config WHERE name='subrepo:%q'",
                          g.zPath);
       if( zAltRepo ){
         int nHost;
@@ -1514,11 +1641,11 @@
 
 /* If the CGI program contains one or more lines of the form
 **
 **    redirect:  repository-filename  http://hostname/path/%s
 **
-** then control jumps here.  Search each repository for an artifact ID 
+** then control jumps here.  Search each repository for an artifact ID
 ** that matches the "name" CGI parameter and for the first match,
 ** redirect to the corresponding URL with the "name" CGI parameter
 ** inserted.  Paint an error page if no match is found.
 **
 ** If there is a line of the form:
@@ -1530,11 +1657,11 @@
 */
 void redirect_web_page(int nRedirect, char **azRedirect){
   int i;                             /* Loop counter */
   const char *zNotFound = 0;         /* Not found URL */
   const char *zName = P("name");
-  set_base_url();          
+  set_base_url();
   if( zName==0 ){
     zName = P("SCRIPT_NAME");
     if( zName && zName[0]=='/' ) zName++;
   }
   if( zName && validate16(zName, strlen(zName)) ){
@@ -1603,11 +1730,11 @@
 **
 ** Usage: %fossil http REPOSITORY ?OPTIONS?
 **
 ** Handle a single HTTP request appearing on stdin.  The resulting webpage
 ** is delivered on stdout.  This method is used to launch an HTTP request
-** handler from inetd, for example.  The argument is the name of the 
+** handler from inetd, for example.  The argument is the name of the
 ** repository.
 **
 ** If REPOSITORY is a directory that contains one or more repositories
 ** with names of the form "*.fossil" then the first element of the URL
 ** pathname selects among the various repositories.  If the pathname does
@@ -1742,11 +1869,11 @@
 ** See also: cgi, http, winsrv
 */
 void cmd_webserver(void){
   int iPort, mxPort;        /* Range of TCP ports allowed */
   const char *zPort;        /* Value of the --port option */
-  char *zBrowser;           /* Name of web browser program */
+  const char *zBrowser;     /* Name of web browser program */
   char *zBrowserCmd = 0;    /* Command to launch the web browser */
   int isUiCmd;              /* True if command is "ui", not "server' */
   const char *zNotFound;    /* The --notfound option or NULL */
   int flags = 0;            /* Server flags */
 
@@ -1779,11 +1906,11 @@
   /* Unix implementation */
   if( isUiCmd ){
 #if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
     zBrowser = db_get("web-browser", 0);
     if( zBrowser==0 ){
-      static char *azBrowserProg[] = { "xdg-open", "gnome-open", "firefox" };
+      static const char *const azBrowserProg[] = { "xdg-open", "gnome-open", "firefox" };
       int i;
       zBrowser = "echo";
       for(i=0; i<sizeof(azBrowserProg)/sizeof(azBrowserProg[0]); i++){
         if( binaryOnPath(azBrowserProg[i]) ){
           zBrowser = azBrowserProg[i];

Index: src/makemake.tcl
==================================================================
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -473,10 +473,15 @@
 # With JSON support
 ifdef FOSSIL_ENABLE_JSON
 TCC += -DFOSSIL_ENABLE_JSON=1
 RCC += -DFOSSIL_ENABLE_JSON=1
 endif
+
+# Fix buggy MinGW command line parsing
+ifdef MINGW_BROKEN_MAINARGS
+TCC += -DMINGW_BROKEN_MAINARGS
+endif
 
 #### We add the -static option here so that we can build a static
 #    executable that will run in a chroot jail.
 #
 LIB = -static

Index: src/printf.c
==================================================================
--- src/printf.c
+++ src/printf.c
@@ -243,11 +243,11 @@
       blob_append(pBlob,"%",1);
       count++;
       break;
     }
     /* Find out what flags are present */
-    flag_leftjustify = flag_plussign = flag_blanksign = 
+    flag_leftjustify = flag_plussign = flag_blanksign =
      flag_alternateform = flag_altform2 = flag_zeropad = 0;
     done = 0;
     do{
       switch( c ){
         case '-':   flag_leftjustify = 1;     break;
@@ -814,25 +814,16 @@
 ** if the output is going to the screen.  If output is redirected into
 ** a file, no translation occurs.  No translation ever occurs on unix.
 */
 void fossil_puts(const char *z, int toStdErr){
 #if defined(_WIN32)
-  static int once = 1;
-  static int istty[2];
-  char *zToFree = 0;
-  if( once ){
-    istty[0] = _isatty(fileno(stdout));
-    istty[1] = _isatty(fileno(stderr));
-    once = 0;
+  if( fossil_utf8_to_console(z, strlen(z), toStdErr) >= 0 ){
+    return;
   }
+#endif
   assert( toStdErr==0 || toStdErr==1 );
-  if( istty[toStdErr] ) z = zToFree = fossil_utf8_to_console(z);
   fwrite(z, 1, strlen(z), toStdErr ? stderr : stdout);
-  free(zToFree);
-#else
-  fwrite(z, 1, strlen(z), toStdErr ? stderr : stdout);
-#endif
   fflush(toStdErr ? stderr : stdout);
 }
 
 /*
 ** Write output for user consumption.  If g.cgiOutput is enabled, then
@@ -863,11 +854,11 @@
     return -1;
   }else if( zB==0 ){
     return +1;
   }else{
     int a, b;
-    do{ 
+    do{
       a = *zA++;
       b = *zB++;
     }while( a==b && a!=0 );
     return ((unsigned char)a) - (unsigned char)b;
   }
@@ -878,11 +869,11 @@
     return -1;
   }else if( zB==0 ){
     return +1;
   }else if( nByte>0 ){
     int a, b;
-    do{ 
+    do{
       a = *zA++;
       b = *zB++;
     }while( a==b && a!=0 && (--nByte)>0 );
     return ((unsigned char)a) - (unsigned char)b;
   }else{

Index: src/winhttp.c
==================================================================
--- src/winhttp.c
+++ src/winhttp.c
@@ -109,11 +109,11 @@
     wanted -= got;
   }
   fclose(out);
   out = 0;
   sqlite3_snprintf(sizeof(zCmd), zCmd, "\"%s\" http \"%s\" %s %s %s --nossl%s",
-    fossil_nameofexe(), g.zRepositoryName, zRequestFName, zReplyFName, 
+    fossil_nameofexe(), g.zRepositoryName, zRequestFName, zReplyFName,
     inet_ntoa(p->addr.sin_addr), p->zOptions
   );
   fossil_system(zCmd);
   in = fossil_fopen(zReplyFName, "rb");
   if( in ){
@@ -129,10 +129,15 @@
   file_delete(zRequestFName);
   file_delete(zReplyFName);
   free(p);
 }
 
+#if !defined(UNICODE)
+#  define fossil_unicode_to_utf8 fossil_mbcs_to_utf8
+#  define fossil_utf8_to_unicode fossil_utf8_to_mbcs
+#endif
+
 /*
 ** Start a listening socket and process incoming HTTP requests on
 ** that socket.
 */
 void win32_http_server(
@@ -146,11 +151,11 @@
   SOCKET s = INVALID_SOCKET;
   SOCKADDR_IN addr;
   int idCnt = 0;
   int iPort = mnPort;
   Blob options;
-  char zTmpPath[MAX_PATH];
+  TCHAR zTmpPath[MAX_PATH];
 
   if( zStopper ) file_delete(zStopper);
   blob_zero(&options);
   if( zNotFound ){
     blob_appendf(&options, " --notfound %s", zNotFound);
@@ -194,11 +199,11 @@
     }
   }
   if( !GetTempPath(MAX_PATH, zTmpPath) ){
     fossil_fatal("unable to get path to the temporary directory.");
   }
-  zTempPrefix = mprintf("%sfossil_server_P%d_", fossil_mbcs_to_utf8(zTmpPath), iPort);
+  zTempPrefix = mprintf("%sfossil_server_P%d_", fossil_unicode_to_utf8(zTmpPath), iPort);
   fossil_print("Listening for HTTP requests on TCP port %d\n", iPort);
   if( zBrowser ){
     zBrowser = mprintf(zBrowser, iPort);
     fossil_print("Launch webbrowser: %s\n", zBrowser);
     fossil_system(zBrowser);
@@ -214,11 +219,11 @@
     int len = sizeof(client_addr);
     int wsaError;
 
     client = accept(s, (struct sockaddr*)&client_addr, &len);
     if( client==INVALID_SOCKET ){
-      /* If the service control handler has closed the listener socket, 
+      /* If the service control handler has closed the listener socket,
       ** cleanup and return, otherwise report a fatal error. */
       wsaError =  WSAGetLastError();
       if( (wsaError==WSAEINTR) || (wsaError==WSAENOTSOCK) ){
         WSACleanup();
         return;
@@ -249,11 +254,11 @@
 struct HttpService {
   int port;                 /* Port on which the http server should run */
   const char *zNotFound;    /* The --notfound option, or NULL */
   int flags;                /* One or more HTTP_SERVER_ flags */
   int isRunningAsService;   /* Are we running as a service ? */
-  const char *zServiceName; /* Name of the service */
+  const TCHAR *zServiceName;/* Name of the service */
   SOCKET s;                 /* Socket on which the http server listens */
 };
 
 /*
 ** Variables used for running as windows service.
@@ -298,11 +303,11 @@
              0,
              NULL
            );
   }
   if( nMsg ){
-    zMsg = fossil_mbcs_to_utf8(tmp);
+    zMsg = fossil_unicode_to_utf8(tmp);
   }else{
     fossil_fatal("unable to get system error message.");
   }
   if( tmp ){
     LocalFree((HLOCAL) tmp);
@@ -326,11 +331,11 @@
   }
   ssStatus.dwCurrentState = dwCurrentState;
   ssStatus.dwWin32ExitCode = dwWin32ExitCode;
   ssStatus.dwWaitHint = dwWaitHint;
 
-  if( (dwCurrentState==SERVICE_RUNNING) || 
+  if( (dwCurrentState==SERVICE_RUNNING) ||
       (dwCurrentState==SERVICE_STOPPED) ){
     ssStatus.dwCheckPoint = 0;
   }else{
     ssStatus.dwCheckPoint++;
   }
@@ -384,11 +389,11 @@
   if( argc>0 ){
     hsData.zServiceName = argv[0];
   }
 
   /* Register the service control handler function */
-  sshStatusHandle = RegisterServiceCtrlHandler("", win32_http_service_ctrl);
+  sshStatusHandle = RegisterServiceCtrlHandler(TEXT(""), win32_http_service_ctrl);
   if( !sshStatusHandle ){
     win32_report_service_status(SERVICE_STOPPED, NO_ERROR, 0);
     return;
   }
 
@@ -429,12 +434,12 @@
   const char *zNotFound,    /* The --notfound option, or NULL */
   int flags                 /* One or more HTTP_SERVER_ flags */
 ){
   /* Define the service table. */
   SERVICE_TABLE_ENTRY ServiceTable[] =
-    {{"", (LPSERVICE_MAIN_FUNCTION)win32_http_service_main}, {NULL, NULL}};
-  
+    {{TEXT(""), (LPSERVICE_MAIN_FUNCTION)win32_http_service_main}, {NULL, NULL}};
+
   /* Initialize the HttpService structure. */
   hsData.port = nPort;
   hsData.zNotFound = zNotFound;
   hsData.flags = flags;
 
@@ -447,11 +452,12 @@
     }
   }
   return 0;
 }
 
-/*
+#ifdef _WIN32
+/* dupe ifdef needed for mkindex
 ** COMMAND: winsrv*
 ** Usage: fossil winsrv METHOD ?SERVICE-NAME? ?OPTIONS?
 **
 ** Where METHOD is one of: create delete show start stop.
 **
@@ -459,11 +465,11 @@
 ** (for example) Fossil to be running in the background when no user
 ** is logged in.
 **
 ** In the following description of the methods, "Fossil-DSCM" will be
 ** used as the default SERVICE-NAME:
-** 
+**
 **    fossil winsrv create ?SERVICE-NAME? ?OPTIONS?
 **
 **         Creates a service. Available options include:
 **
 **         -D|--display DISPLAY-NAME
@@ -565,11 +571,11 @@
 
   if( strncmp(zMethod, "create", n)==0 ){
     SC_HANDLE hScm;
     SC_HANDLE hSvc;
     SERVICE_DESCRIPTION
-      svcDescr = {"Fossil - Distributed Software Configuration Management"};
+      svcDescr = {TEXT("Fossil - Distributed Software Configuration Management")};
     char *zErrFmt = "unable to create service '%s': %s";
     DWORD dwStartType = SERVICE_DEMAND_START;
     const char *zDisplay    = find_option("display", "D", 1);
     const char *zStart      = find_option("start", "S", 1);
     const char *zUsername   = find_option("username", "U", 1);
@@ -624,22 +630,22 @@
     /* Create the service. */
     hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
     if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
     hSvc = CreateService(
              hScm,                                    /* Handle to the SCM */
-             fossil_utf8_to_mbcs(zSvcName),           /* Name of the service */
-             fossil_utf8_to_mbcs(zDisplay),           /* Display name */
+             fossil_utf8_to_unicode(zSvcName),           /* Name of the service */
+             fossil_utf8_to_unicode(zDisplay),           /* Display name */
              SERVICE_ALL_ACCESS,                      /* Desired access */
              SERVICE_WIN32_OWN_PROCESS,               /* Service type */
              dwStartType,                             /* Start type */
              SERVICE_ERROR_NORMAL,                    /* Error control */
-             fossil_utf8_to_mbcs(blob_str(&binPath)), /* Binary path */
+             fossil_utf8_to_unicode(blob_str(&binPath)), /* Binary path */
              NULL,                                    /* Load ordering group */
              NULL,                                    /* Tag value */
              NULL,                                    /* Service dependencies */
-             fossil_utf8_to_mbcs(zUsername),          /* Service account */
-             fossil_utf8_to_mbcs(zPassword)           /* Account password */
+             fossil_utf8_to_unicode(zUsername),          /* Service account */
+             fossil_utf8_to_unicode(zPassword)           /* Account password */
            );
     if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
     /* Set the service description. */
     ChangeServiceConfig2(hSvc, SERVICE_CONFIG_DESCRIPTION, &svcDescr);
     fossil_print("Service '%s' successfully created.\n", zSvcName);
@@ -658,11 +664,11 @@
     }else if( g.argc>4 ){
       fossil_fatal("to much arguments for delete method.");
     }
     hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
     if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
-    hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), SERVICE_ALL_ACCESS);
+    hSvc = OpenService(hScm, fossil_utf8_to_unicode(zSvcName), SERVICE_ALL_ACCESS);
     if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
     QueryServiceStatus(hSvc, &sstat);
     if( sstat.dwCurrentState!=SERVICE_STOPPED ){
       fossil_print("Stopping service '%s'", zSvcName);
       if( sstat.dwCurrentState!=SERVICE_STOP_PENDING ){
@@ -695,28 +701,28 @@
     SERVICE_STATUS sstat;
     LPQUERY_SERVICE_CONFIG pSvcConfig;
     LPSERVICE_DESCRIPTION pSvcDescr;
     BOOL bStatus;
     DWORD nRequired;
-    char *zErrFmt = "unable to show service '%s': %s";
-    static const char *zSvcTypes[] = {
+    const char *zErrFmt = "unable to show service '%s': %s";
+    static const char *const zSvcTypes[] = {
       "Driver service",
       "File system driver service",
       "Service runs in its own process",
       "Service shares a process with other services",
       "Service can interact with the desktop"
     };
     const char *zSvcType = "";
-    static char *zSvcStartTypes[] = {
+    static const char *const zSvcStartTypes[] = {
       "Started by the system loader",
       "Started by the IoInitSystem function",
       "Started automatically by the service control manager",
       "Started manually",
       "Service cannot be started"
     };
     const char *zSvcStartType = "";
-    static const char *zSvcStates[] = {
+    static const char *const zSvcStates[] = {
       "Stopped", "Starting", "Stopping", "Running",
       "Continue pending", "Pause pending", "Paused"
     };
     const char *zSvcState = "";
 
@@ -726,11 +732,11 @@
     }else if( g.argc>4 ){
       fossil_fatal("to much arguments for show method.");
     }
     hScm = OpenSCManager(NULL, NULL, GENERIC_READ);
     if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
-    hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), GENERIC_READ);
+    hSvc = OpenService(hScm, fossil_utf8_to_unicode(zSvcName), GENERIC_READ);
     if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
     /* Get the service configuration */
     bStatus = QueryServiceConfig(hSvc, NULL, 0, &nRequired);
     if( !bStatus && GetLastError()!=ERROR_INSUFFICIENT_BUFFER ){
       fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
@@ -778,19 +784,19 @@
       case SERVICE_PAUSED:           zSvcState = zSvcStates[6]; break;
     }
     /* Print service information to terminal */
     fossil_print("Service name .......: %s\n", zSvcName);
     fossil_print("Display name .......: %s\n",
-                 fossil_mbcs_to_utf8(pSvcConfig->lpDisplayName));
+                 fossil_unicode_to_utf8(pSvcConfig->lpDisplayName));
     fossil_print("Service description : %s\n",
-                 fossil_mbcs_to_utf8(pSvcDescr->lpDescription));
+                 fossil_unicode_to_utf8(pSvcDescr->lpDescription));
     fossil_print("Service type .......: %s.\n", zSvcType);
     fossil_print("Service start type .: %s.\n", zSvcStartType);
     fossil_print("Binary path name ...: %s\n",
-                 fossil_mbcs_to_utf8(pSvcConfig->lpBinaryPathName));
+                 fossil_unicode_to_utf8(pSvcConfig->lpBinaryPathName));
     fossil_print("Service username ...: %s\n",
-                 fossil_mbcs_to_utf8(pSvcConfig->lpServiceStartName));
+                 fossil_unicode_to_utf8(pSvcConfig->lpServiceStartName));
     fossil_print("Current state ......: %s.\n", zSvcState);
     /* Cleanup */
     fossil_free(pSvcConfig);
     fossil_free(pSvcDescr);
     CloseServiceHandle(hSvc);
@@ -808,11 +814,11 @@
     }else if( g.argc>4 ){
       fossil_fatal("to much arguments for start method.");
     }
     hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
     if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
-    hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), SERVICE_ALL_ACCESS);
+    hSvc = OpenService(hScm, fossil_utf8_to_unicode(zSvcName), SERVICE_ALL_ACCESS);
     if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
     QueryServiceStatus(hSvc, &sstat);
     if( sstat.dwCurrentState!=SERVICE_RUNNING ){
       fossil_print("Starting service '%s'", zSvcName);
       if( sstat.dwCurrentState!=SERVICE_START_PENDING ){
@@ -844,11 +850,11 @@
     }else if( g.argc>4 ){
       fossil_fatal("to much arguments for stop method.");
     }
     hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
     if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
-    hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), SERVICE_ALL_ACCESS);
+    hSvc = OpenService(hScm, fossil_utf8_to_unicode(zSvcName), SERVICE_ALL_ACCESS);
     if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
     QueryServiceStatus(hSvc, &sstat);
     if( sstat.dwCurrentState!=SERVICE_STOPPED ){
       fossil_print("Stopping service '%s'", zSvcName);
       if( sstat.dwCurrentState!=SERVICE_STOP_PENDING ){
@@ -872,7 +878,8 @@
     fossil_fatal("METHOD should be one of:"
                  " create delete show start stop");
   }
   return;
 }
+#endif /* _WIN32 */
 
 #endif /* _WIN32  -- This code is for win32 only */

ADDED   test/cmdline.test
Index: test/cmdline.test
==================================================================
--- test/cmdline.test
+++ test/cmdline.test
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 2011 D. Richard Hipp
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the Simplified BSD License (also
+# known as the "2-Clause License" or "FreeBSD License".)
+#
+# This program is distributed in the hope that it will be useful,
+# but without any warranty; without even the implied warranty of
+# merchantability or fitness for a particular purpose.
+#
+# Author contact information:
+#   drh@hwaci.com
+#   http://www.hwaci.com/drh/
+#
+############################################################################
+#
+# Test command line parsing
+#
+
+proc cmd-line {testname args} {
+  set i 1
+  foreach {cmdline result} $args {
+    fossil test-echo {*}$cmdline
+    test cmd-line-$testname.$i {[lrange [split $::RESULT \n] 2 end]=="\{argv\[2\] = \[$result\]\}"}
+    incr i
+  }
+}
+cmd-line 100 abc abc {"abc"} abc
+cmd-line 101 * {*} *.* {*.*}

Index: win/Makefile.mingw
==================================================================
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -145,10 +145,15 @@
 # With JSON support
 ifdef FOSSIL_ENABLE_JSON
 TCC += -DFOSSIL_ENABLE_JSON=1
 RCC += -DFOSSIL_ENABLE_JSON=1
 endif
+
+# Fix buggy MinGW command line parsing
+ifdef MINGW_BROKEN_MAINARGS
+TCC += -DMINGW_BROKEN_MAINARGS
+endif
 
 #### We add the -static option here so that we can build a static
 #    executable that will run in a chroot jail.
 #
 LIB = -static

Index: win/Makefile.msc
==================================================================
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -32,11 +32,11 @@
 ZLIBDIR = $(MSCDIR)\extra\lib
 ZLIB    = zlib.lib
 
 INCL   = -I. -I$(SRCDIR) -I$B\win\include -I$(MSCDIR)\extra\include -I$(ZINCDIR)
 
-CFLAGS = -nologo -MT -O2
+CFLAGS = -nologo -MT -O2 -DUNICODE -D_UNICODE
 BCC    = $(CC) $(CFLAGS)
 TCC    = $(CC) -c $(CFLAGS) $(MSCDEF) $(SSL) $(INCL)
 LIBS   = $(ZLIB) ws2_32.lib advapi32.lib $(SSLLIB)
 LIBDIR = -LIBPATH:$(MSCDIR)\extra\lib -LIBPATH:$(ZLIBDIR)