]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/win32/compat/compat.cpp
Tweak put compat.cpp debug on variable
[bacula/bacula] / bacula / src / win32 / compat / compat.cpp
index c421822c18ee9cf60624f0e987db403895ee0109..d662f0279f7ede19bdeaa16962baff7dc7ea424d 100644 (file)
@@ -1,12 +1,12 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2004-2007 Free Software Foundation Europe e.V.
+   Copyright (C) 2004-2010 Free Software Foundation Europe e.V.
 
    The main author of Bacula is Kern Sibbald, with contributions from
    many others, a complete list can be found in the file AUTHORS.
    This program is Free Software; you can redistribute it and/or
-   modify it under the terms of version two of the GNU General Public
+   modify it under the terms of version three of the GNU Affero General Public
    License as published by the Free Software Foundation and included
    in the file LICENSE.
 
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    General Public License for more details.
 
-   You should have received a copy of the GNU General Public License
+   You should have received a copy of the GNU Affero General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Bacula® is a registered trademark of John Walker.
+   Bacula® is a registered trademark of Kern Sibbald.
    The licensor of Bacula is the Free Software Foundation Europe
    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
    Switzerland, email:ftf@fsfeurope.org.
 //
 // Author          : Christopher S. Hull
 // Created On      : Sat Jan 31 15:55:00 2004
-// $Id$
 
 
 #include "bacula.h"
 #include "compat.h"
 #include "jcr.h"
+#include "findlib/find.h"
+
+static const int dbglvl = 500;
 
 #define b_errno_win32 (1<<29)
 
 #define MAX_PATHLENGTH  1024
 
-/* UTF-8 to UCS2 path conversion is expensive,
+/**
+   UTF-8 to UCS2 path conversion is expensive,
    so we cache the conversion. During backup the
    conversion is called 3 times (lstat, attribs, open),
-   by using the cache this is reduced to 1 time */
-
-static POOLMEM *g_pWin32ConvUTF8Cache = get_pool_memory(PM_FNAME);
-static POOLMEM *g_pWin32ConvUCS2Cache = get_pool_memory(PM_FNAME);
+   by using the cache this is reduced to 1 time
+ */
+static POOLMEM *g_pWin32ConvUTF8Cache = NULL;
+static POOLMEM *g_pWin32ConvUCS2Cache = NULL;
 static DWORD g_dwWin32ConvUTF8strlen = 0;
 static pthread_mutex_t Win32Convmutex = PTHREAD_MUTEX_INITIALIZER;
 
 static t_pVSSPathConvert   g_pVSSPathConvert;
 static t_pVSSPathConvertW  g_pVSSPathConvertW;
 
+/* Forward referenced functions */
+static const char *errorString(void);
+
+
 void SetVSSPathConvert(t_pVSSPathConvert pPathConvert, t_pVSSPathConvertW pPathConvertW)
 {
    g_pVSSPathConvert = pPathConvert;
    g_pVSSPathConvertW = pPathConvertW;
 }
 
+static void Win32ConvInitCache()
+{
+   if (g_pWin32ConvUTF8Cache) {
+      return;
+   }
+   g_pWin32ConvUTF8Cache = get_pool_memory(PM_FNAME);
+   g_pWin32ConvUCS2Cache = get_pool_memory(PM_FNAME);
+}
+
 void Win32ConvCleanupCache()
 {
+   P(Win32Convmutex);
    if (g_pWin32ConvUTF8Cache) {
       free_pool_memory(g_pWin32ConvUTF8Cache);
       g_pWin32ConvUTF8Cache = NULL;
@@ -77,6 +94,7 @@ void Win32ConvCleanupCache()
    }
 
    g_dwWin32ConvUTF8strlen = 0;
+   V(Win32Convmutex);
 }
 
 
@@ -90,7 +108,7 @@ void Win32ConvCleanupCache()
 extern DWORD   g_platform_id;
 extern DWORD   g_MinorVersion;
 
-// from MicroSoft SDK (KES) is the diff between Jan 1 1601 and Jan 1 1970
+/* From Microsoft SDK (KES) is the diff between Jan 1 1601 and Jan 1 1970 */
 #ifdef HAVE_MINGW
 #define WIN32_FILETIME_ADJUST 0x19DB1DED53E8000ULL 
 #else
@@ -99,12 +117,16 @@ extern DWORD   g_MinorVersion;
 
 #define WIN32_FILETIME_SCALE  10000000             // 100ns/second
 
-void conv_unix_to_win32_path(const char *name, char *win32_name, DWORD dwSize)
+/**
+ * Convert from UTF-8 to VSS Windows path/file 
+ *  Used by compatibility layer for Unix system calls
+ */
+static void conv_unix_to_vss_win32_path(const char *name, char *win32_name, DWORD dwSize)
 {
     const char *fname = name;
     char *tname = win32_name;
 
-    Dmsg0(100, "Enter convert_unix_to_win32_path\n");
+    Dmsg0(dbglvl, "Enter convert_unix_to_win32_path\n");
 
     if (IsPathSeparator(name[0]) &&
         IsPathSeparator(name[1]) &&
@@ -127,7 +149,7 @@ void conv_unix_to_win32_path(const char *name, char *win32_name, DWORD dwSize)
     }
 
     while (*name) {
-        /* Check for Unix separator and convert to Win32 */
+        /** Check for Unix separator and convert to Win32 */
         if (name[0] == '/' && name[1] == '/') {  /* double slash? */
            name++;                               /* yes, skip first one */
         }
@@ -142,20 +164,21 @@ void conv_unix_to_win32_path(const char *name, char *win32_name, DWORD dwSize)
         }
         name++;
     }
-    /* Strip any trailing slash, if we stored something */
-    /* but leave "c:\" with backslash (root directory case */
+    /** Strip any trailing slash, if we stored something
+     * but leave "c:\" with backslash (root directory case
+     */
     if (*fname != 0 && win32_name[-1] == '\\' && strlen (fname) != 3) {
         win32_name[-1] = 0;
     } else {
         *win32_name = 0;
     }
 
-    /* here we convert to VSS specific file name which
+    /** here we convert to VSS specific file name which
        can get longer because VSS will make something like
        \\\\?\\GLOBALROOT\\Device\\HarddiskVolumeShadowCopy1\\bacula\\uninstall.exe
        from c:\bacula\uninstall.exe
     */
-    Dmsg1(100, "path=%s\n", tname);
+    Dmsg1(dbglvl, "path=%s\n", tname);
     if (g_pVSSPathConvert != NULL) {
        POOLMEM *pszBuf = get_pool_memory (PM_FNAME);
        pszBuf = check_pool_memory_size(pszBuf, dwSize);
@@ -164,40 +187,42 @@ void conv_unix_to_win32_path(const char *name, char *win32_name, DWORD dwSize)
        free_pool_memory(pszBuf);
     }
 
-    Dmsg1(100, "Leave cvt_u_to_win32_path path=%s\n", tname);
+    Dmsg1(dbglvl, "Leave cvt_u_to_win32_path path=%s\n", tname);
 }
 
-/* Conversion of a Unix filename to a Win32 filename */
+/** Conversion of a Unix filename to a Win32 filename */
 void unix_name_to_win32(POOLMEM **win32_name, char *name)
 {
    /* One extra byte should suffice, but we double it */
    /* add MAX_PATH bytes for VSS shadow copy name */
    DWORD dwSize = 2*strlen(name)+MAX_PATH;
    *win32_name = check_pool_memory_size(*win32_name, dwSize);
-   conv_unix_to_win32_path(name, *win32_name, dwSize);
+   conv_unix_to_vss_win32_path(name, *win32_name, dwSize);
 }
 
-POOLMEM* 
+
+/**
+ * This function expects an UCS-encoded standard wchar_t in pszUCSPath and
+ * will complete the input path to an absolue path of the form \\?\c:\path\file
+ * 
+ * With this trick, it is possible to have 32K characters long paths.
+ *
+ * Optionally one can use pBIsRawPath to determine id pszUCSPath contains a path
+ * to a raw windows partition.  
+ *
+ *        created 02/27/2006 Thorsten Engel
+ */
+static POOLMEM* 
 make_wchar_win32_path(POOLMEM *pszUCSPath, BOOL *pBIsRawPath /*= NULL*/)
 {
-   /* created 02/27/2006 Thorsten Engel
-    * 
-    * This function expects an UCS-encoded standard wchar_t in pszUCSPath and
-    * will complete the input path to an absolue path of the form \\?\c:\path\file
-    * 
-    * With this trick, it is possible to have 32K characters long paths.
-    *
-    * Optionally one can use pBIsRawPath to determine id pszUCSPath contains a path
-    * to a raw windows partition.  
-    */
 
-   Dmsg0(100, "Enter wchar_win32_path\n");
+   Dmsg0(dbglvl, "Enter wchar_win32_path\n");
    if (pBIsRawPath) {
       *pBIsRawPath = FALSE;              /* Initialize, set later */
    }
 
    if (!p_GetCurrentDirectoryW) {
-      Dmsg0(100, "Leave wchar_win32_path no change \n");
+      Dmsg0(dbglvl, "Leave wchar_win32_path no change \n");
       return pszUCSPath;
    }
    
@@ -205,7 +230,7 @@ make_wchar_win32_path(POOLMEM *pszUCSPath, BOOL *pBIsRawPath /*= NULL*/)
 
    /* if it has already the desired form, exit without changes */
    if (wcslen(name) > 3 && wcsncmp(name, L"\\\\?\\", 4) == 0) {
-      Dmsg0(100, "Leave wchar_win32_path no change \n");
+      Dmsg0(dbglvl, "Leave wchar_win32_path no change \n");
       return pszUCSPath;
    }
 
@@ -375,23 +400,25 @@ make_wchar_win32_path(POOLMEM *pszUCSPath, BOOL *pBIsRawPath /*= NULL*/)
    free_pool_memory(pszUCSPath);
    free_pool_memory((POOLMEM *)pwszCurDirBuf);
 
-   Dmsg1(100, "Leave wchar_win32_path=%s\n", pwszBuf);
+   Dmsg1(dbglvl, "Leave wchar_win32_path=%s\n", pwszBuf);
    return (POOLMEM *)pwszBuf;
 }
 
 int
 wchar_2_UTF8(char *pszUTF, const wchar_t *pszUCS, int cchChar)
 {
-   /* the return value is the number of bytes written to the buffer.
-      The number includes the byte for the null terminator. */
+   /**
+    * The return value is the number of bytes written to the buffer.
+    * The number includes the byte for the null terminator.
+    */
 
    if (p_WideCharToMultiByte) {
-         int nRet = p_WideCharToMultiByte(CP_UTF8,0,pszUCS,-1,pszUTF,cchChar,NULL,NULL);
-         ASSERT (nRet > 0);
-         return nRet;
-      }
-   else
+      int nRet = p_WideCharToMultiByte(CP_UTF8,0,pszUCS,-1,pszUTF,cchChar,NULL,NULL);
+      ASSERT (nRet > 0);
+      return nRet;
+   } else {
       return 0;
+   }
 }
 
 int
@@ -408,9 +435,9 @@ UTF8_2_wchar(POOLMEM **ppszUCS, const char *pszUTF)
       int nRet = p_MultiByteToWideChar(CP_UTF8, 0, pszUTF, -1, (LPWSTR) *ppszUCS,cchSize);
       ASSERT (nRet > 0);
       return nRet;
-   }
-   else
+   } else {
       return 0;
+   }
 }
 
 
@@ -446,11 +473,14 @@ make_win32_path_UTF8_2_wchar(POOLMEM **pszUCS, const char *pszUTF, BOOL* pBIsRaw
    /* if we find the utf8 string in cache, we use the cached ucs2 version.
       we compare the stringlength first (quick check) and then compare the content.            
    */
-   if (g_dwWin32ConvUTF8strlen == strlen(pszUTF)) {
+   if (!g_pWin32ConvUTF8Cache) {
+      Win32ConvInitCache();
+   } else if (g_dwWin32ConvUTF8strlen == strlen(pszUTF)) {
       if (bstrcmp(pszUTF, g_pWin32ConvUTF8Cache)) {
+         /* Return cached value */
          int32_t nBufSize = sizeof_pool_memory(g_pWin32ConvUCS2Cache);
          *pszUCS = check_pool_memory_size(*pszUCS, nBufSize);      
-         wcscpy((LPWSTR) *pszUCS, (LPWSTR) g_pWin32ConvUCS2Cache);
+         wcscpy((LPWSTR) *pszUCS, (LPWSTR)g_pWin32ConvUCS2Cache);
          V(Win32Convmutex);
          return nBufSize / sizeof (WCHAR);
       }
@@ -472,7 +502,7 @@ make_win32_path_UTF8_2_wchar(POOLMEM **pszUCS, const char *pszUTF, BOOL* pBIsRaw
    wcscpy((LPWSTR) g_pWin32ConvUCS2Cache, (LPWSTR) *pszUCS);
    
    g_dwWin32ConvUTF8strlen = strlen(pszUTF);
-   g_pWin32ConvUTF8Cache = check_pool_memory_size(g_pWin32ConvUTF8Cache, g_dwWin32ConvUTF8strlen+1);
+   g_pWin32ConvUTF8Cache = check_pool_memory_size(g_pWin32ConvUTF8Cache, g_dwWin32ConvUTF8strlen+2);
    bstrncpy(g_pWin32ConvUTF8Cache, pszUTF, g_dwWin32ConvUTF8strlen+1);
    V(Win32Convmutex);
 
@@ -486,12 +516,44 @@ int umask(int)
 }
 #endif
 
-int fcntl(int fd, int cmd)
+#ifndef LOAD_WITH_ALTERED_SEARCH_PATH
+#define LOAD_WITH_ALTERED_SEARCH_PATH 0x00000008
+#endif
+
+void *dlopen(const char *file, int mode)
 {
-   return 0;
+   void *handle;
+
+   handle = LoadLibraryEx(file, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
+   return handle;
+}
+
+void *dlsym(void *handle, const char *name)
+{
+   void *symaddr;
+   symaddr = (void *)GetProcAddress((HMODULE)handle, name);
+   return symaddr;
+}
+
+int dlclose(void *handle) 
+{
+   if (handle && !FreeLibrary((HMODULE)handle)) {
+      errno = b_errno_win32;
+      return 1;        /* failed */
+   }
+   return 0;           /* OK */
 }
 
-int chmod(const char *, mode_t)
+char *dlerror(void) 
+{
+   static char buf[200];
+   const char *err = errorString();
+   bstrncpy(buf, (char *)err, sizeof(buf));
+   LocalFree((void *)err);
+   return buf;
+}
+
+int fcntl(int fd, int cmd)
 {
    return 0;
 }
@@ -548,8 +610,7 @@ cvt_ftime_to_utime(const FILETIME &time)
     return (time_t) (mstime & 0xffffffff);
 }
 
-static const char *
-errorString(void)
+static const char *errorString(void)
 {
    LPVOID lpMsgBuf;
 
@@ -584,21 +645,28 @@ statDir(const char *file, struct stat *sb)
    WIN32_FIND_DATAA info_a;       // window's file info
 
    // cache some common vars to make code more transparent
-   DWORD* pdwFileAttributes;
-   DWORD* pnFileSizeHigh;
-   DWORD* pnFileSizeLow;
-   FILETIME* pftLastAccessTime;
-   FILETIME* pftLastWriteTime;
-   FILETIME* pftCreationTime;
+   DWORD *pdwFileAttributes;
+   DWORD *pnFileSizeHigh;
+   DWORD *pnFileSizeLow;
+   DWORD *pdwReserved0;
+   FILETIME *pftLastAccessTime;
+   FILETIME *pftLastWriteTime;
+   FILETIME *pftCreationTime;
 
+   /* 
+    * Oh, cool, another exception: Microsoft doesn't let us do 
+    *  FindFile operations on a Drive, so simply fake root attibutes.
+    */
    if (file[1] == ':' && file[2] == 0) {
-        Dmsg1(99, "faking ROOT attrs(%s).\n", file);
-        sb->st_mode = S_IFDIR;
-        sb->st_mode |= S_IREAD|S_IEXEC|S_IWRITE;
-        time(&sb->st_ctime);
-        time(&sb->st_mtime);
-        time(&sb->st_atime);
-        return 0;
+      time_t now = time(NULL);
+      Dmsg1(dbglvl, "faking ROOT attrs(%s).\n", file);
+      sb->st_mode = S_IFDIR;
+      sb->st_mode |= S_IREAD|S_IEXEC|S_IWRITE;
+      sb->st_ctime = now;
+      sb->st_mtime = now;
+      sb->st_atime = now;
+      sb->st_rdev = 0;
+      return 0;
     }
 
    HANDLE h = INVALID_HANDLE_VALUE;
@@ -608,10 +676,12 @@ statDir(const char *file, struct stat *sb)
       POOLMEM* pwszBuf = get_pool_memory (PM_FNAME);
       make_win32_path_UTF8_2_wchar(&pwszBuf, file);
 
-      h = p_FindFirstFileW((LPCWSTR) pwszBuf, &info_w);
+      Dmsg1(dbglvl, "FindFirstFileW=%s\n", file);
+      h = p_FindFirstFileW((LPCWSTR)pwszBuf, &info_w);
       free_pool_memory(pwszBuf);
 
       pdwFileAttributes = &info_w.dwFileAttributes;
+      pdwReserved0      = &info_w.dwReserved0;
       pnFileSizeHigh    = &info_w.nFileSizeHigh;
       pnFileSizeLow     = &info_w.nFileSizeLow;
       pftLastAccessTime = &info_w.ftLastAccessTime;
@@ -620,22 +690,32 @@ statDir(const char *file, struct stat *sb)
 
    // use ASCII
    } else if (p_FindFirstFileA) {
+      Dmsg1(dbglvl, "FindFirstFileA=%s\n", file);
       h = p_FindFirstFileA(file, &info_a);
 
       pdwFileAttributes = &info_a.dwFileAttributes;
+      pdwReserved0      = &info_a.dwReserved0;
       pnFileSizeHigh    = &info_a.nFileSizeHigh;
       pnFileSizeLow     = &info_a.nFileSizeLow;
       pftLastAccessTime = &info_a.ftLastAccessTime;
       pftLastWriteTime  = &info_a.ftLastWriteTime;
       pftCreationTime   = &info_a.ftCreationTime;
+   } else {
+      Dmsg0(dbglvl, "No findFirstFile A or W found\n");
    }
 
    if (h == INVALID_HANDLE_VALUE) {
       const char *err = errorString();
-      Dmsg2(99, "FindFirstFile(%s):%s\n", file, err);
+      /*
+       * Note, in creating leading paths, it is normal that
+       * the file does not exist.
+       */
+      Dmsg2(2099, "FindFirstFile(%s):%s\n", file, err);
       LocalFree((void *)err);
       errno = b_errno_win32;
       return -1;
+   } else {
+      FindClose(h);
    }
 
    sb->st_mode = 0777;               /* start with everything */
@@ -647,10 +727,23 @@ statDir(const char *file, struct stat *sb)
        sb->st_mode |= S_ISVTX; /* use sticky bit -> hidden */
    sb->st_mode |= S_IFDIR;
 
-   /* Use st_rdev to store reparse attribute */
-   sb->st_rdev = (*pdwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ? 1 : 0; 
-
-
+   /* 
+    * Store reparse/mount point info in st_rdev.  Note a
+    *  Win32 reparse point (junction point) is like a link
+    *  though it can have many properties (directory link,
+    *  soft link, hard link, HSM, ...
+    *  A mount point is a reparse point where another volume
+    *  is mounted, so it is like a Unix mount point (change of
+    *  filesystem).
+    */
+   if (*pdwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
+      if (*pdwReserved0 & IO_REPARSE_TAG_MOUNT_POINT) {
+         sb->st_rdev = WIN32_MOUNT_POINT;           /* mount point */
+      } else {
+         sb->st_rdev = WIN32_REPARSE_POINT;         /* reparse point */
+      }
+   }  
+   Dmsg2(dbglvl, "st_rdev=%d file=%s\n", sb->st_rdev, file);
    sb->st_size = *pnFileSizeHigh;
    sb->st_size <<= 32;
    sb->st_size |= *pnFileSizeLow;
@@ -660,20 +753,18 @@ statDir(const char *file, struct stat *sb)
    sb->st_atime = cvt_ftime_to_utime(*pftLastAccessTime);
    sb->st_mtime = cvt_ftime_to_utime(*pftLastWriteTime);
    sb->st_ctime = cvt_ftime_to_utime(*pftCreationTime);
-   FindClose(h);
 
    return 0;
 }
 
 int
-fstat(int fd, struct stat *sb)
+fstat(intptr_t fd, struct stat *sb)
 {
    BY_HANDLE_FILE_INFORMATION info;
-   char tmpbuf[1024];
 
-   if (!GetFileInformationByHandle((HANDLE)fd, &info)) {
+   if (!GetFileInformationByHandle((HANDLE)_get_osfhandle(fd), &info)) {
        const char *err = errorString();
-       Dmsg2(99, "GetfileInformationByHandle(%s): %s\n", tmpbuf, err);
+       Dmsg1(2099, "GetfileInformationByHandle: %s\n", err);
        LocalFree((void *)err);
        errno = b_errno_win32;
        return -1;
@@ -685,7 +776,7 @@ fstat(int fd, struct stat *sb)
    sb->st_ino |= info.nFileIndexLow;
    sb->st_nlink = (short)info.nNumberOfLinks;
    if (sb->st_nlink > 1) {
-      Dmsg1(99,  "st_nlink=%d\n", sb->st_nlink);
+      Dmsg1(dbglvl,  "st_nlink=%d\n", sb->st_nlink);
    }
 
    sb->st_mode = 0777;               /* start with everything */
@@ -698,7 +789,11 @@ fstat(int fd, struct stat *sb)
    sb->st_mode |= S_IFREG;
 
    /* Use st_rdev to store reparse attribute */
-   sb->st_rdev = (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ? 1 : 0; 
+   if  (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
+      sb->st_rdev = WIN32_REPARSE_POINT;
+   }
+   Dmsg3(dbglvl, "st_rdev=%d sizino=%d ino=%lld\n", sb->st_rdev, sizeof(sb->st_ino),
+      (long long)sb->st_ino);
 
    sb->st_size = info.nFileSizeHigh;
    sb->st_size <<= 32;
@@ -715,10 +810,10 @@ fstat(int fd, struct stat *sb)
 static int
 stat2(const char *file, struct stat *sb)
 {
-   HANDLE h;
+   HANDLE h = INVALID_HANDLE_VALUE;
    int rval = 0;
-   char tmpbuf[1024];
-   conv_unix_to_win32_path(file, tmpbuf, 1024);
+   char tmpbuf[5000];
+   conv_unix_to_vss_win32_path(file, tmpbuf, 5000);
 
    DWORD attr = (DWORD)-1;
 
@@ -727,37 +822,43 @@ stat2(const char *file, struct stat *sb)
       make_win32_path_UTF8_2_wchar(&pwszBuf, tmpbuf);
 
       attr = p_GetFileAttributesW((LPCWSTR) pwszBuf);
+      if (p_CreateFileW) {
+         h = CreateFileW((LPCWSTR)pwszBuf, GENERIC_READ,
+                FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
+      }
       free_pool_memory(pwszBuf);
    } else if (p_GetFileAttributesA) {
       attr = p_GetFileAttributesA(tmpbuf);
+      h = CreateFileA(tmpbuf, GENERIC_READ,
+               FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
    }
 
    if (attr == (DWORD)-1) {
       const char *err = errorString();
-      Dmsg2(99, "GetFileAttributes(%s): %s\n", tmpbuf, err);
+      Dmsg2(2099, "GetFileAttributes(%s): %s\n", tmpbuf, err);
       LocalFree((void *)err);
+      if (h != INVALID_HANDLE_VALUE) {
+         CloseHandle(h);
+      }
       errno = b_errno_win32;
       return -1;
    }
 
-   if (attr & FILE_ATTRIBUTE_DIRECTORY) {
-      return statDir(tmpbuf, sb);
-   }
-
-   h = CreateFileA(tmpbuf, GENERIC_READ,
-                  FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
-
    if (h == INVALID_HANDLE_VALUE) {
       const char *err = errorString();
-      Dmsg2(99, "Cannot open file for stat (%s):%s\n", tmpbuf, err);
+      Dmsg2(2099, "Cannot open file for stat (%s):%s\n", tmpbuf, err);
       LocalFree((void *)err);
       errno = b_errno_win32;
       return -1;
    }
 
-   rval = fstat((int)h, sb);
+   rval = fstat((intptr_t)h, sb);
    CloseHandle(h);
 
+   if (attr & FILE_ATTRIBUTE_DIRECTORY &&
+        file[1] == ':' && file[2] != 0) {
+      rval = statDir(file, sb);
+   }
    return rval;
 }
 
@@ -767,27 +868,20 @@ stat(const char *file, struct stat *sb)
    WIN32_FILE_ATTRIBUTE_DATA data;
    errno = 0;
 
-
    memset(sb, 0, sizeof(*sb));
 
-   /* why not allow win 95 to use p_GetFileAttributesExA ? 
-    * this function allows _some_ open files to be stat'ed 
-    * if (g_platform_id == VER_PLATFORM_WIN32_WINDOWS) {
-    *    return stat2(file, sb);
-    * }
-    */
-
    if (p_GetFileAttributesExW) {
       /* dynamically allocate enough space for UCS2 filename */
-      POOLMEM* pwszBuf = get_pool_memory (PM_FNAME);
+      POOLMEM *pwszBuf = get_pool_memory(PM_FNAME);
       make_win32_path_UTF8_2_wchar(&pwszBuf, file);
 
-      BOOL b = p_GetFileAttributesExW((LPCWSTR) pwszBuf, GetFileExInfoStandard, &data);
+      BOOL b = p_GetFileAttributesExW((LPCWSTR)pwszBuf, GetFileExInfoStandard, &data);
       free_pool_memory(pwszBuf);
 
       if (!b) {
          return stat2(file, sb);
       }
+
    } else if (p_GetFileAttributesExA) {
       if (!p_GetFileAttributesExA(file, GetFileExInfoStandard, &data)) {
          return stat2(file, sb);
@@ -824,6 +918,21 @@ stat(const char *file, struct stat *sb)
    sb->st_atime = cvt_ftime_to_utime(data.ftLastAccessTime);
    sb->st_mtime = cvt_ftime_to_utime(data.ftLastWriteTime);
    sb->st_ctime = cvt_ftime_to_utime(data.ftCreationTime);
+
+   /*
+    * If we are not at the root, then to distinguish a reparse 
+    *  point from a mount point, we must call FindFirstFile() to
+    *  get the WIN32_FIND_DATA, which has the bit that indicates
+    *  that this directory is a mount point -- aren't Win32 APIs
+    *  wonderful? (sarcasm).  The code exists in the statDir
+    *  subroutine.
+    */
+   if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY && 
+        file[1] == ':' && file[2] != 0) {
+      statDir(file, sb);
+   }
+   Dmsg3(dbglvl, "sizino=%d ino=%lld file=%s\n", sizeof(sb->st_ino),
+                       (long long)sb->st_ino, file);
    return 0;
 }
 
@@ -1002,12 +1111,30 @@ gettimeofday(struct timeval *tv, struct timezone *)
 
 }
 
-/* For apcupsd this is in src/lib/wincompat.c */
+/* 
+ * Write in Windows System log 
+ */
 extern "C" void syslog(int type, const char *fmt, ...) 
 {
-/*#ifndef HAVE_CONSOLE
-    MessageBox(NULL, msg, "Bacula", MB_OK);
-#endif*/
+   va_list   arg_ptr;
+   int len, maxlen;
+   POOLMEM *msg;
+
+   msg = get_pool_memory(PM_EMSG);
+
+   for (;;) {
+      maxlen = sizeof_pool_memory(msg) - 1;
+      va_start(arg_ptr, fmt);
+      len = bvsnprintf(msg, maxlen, fmt, arg_ptr);
+      va_end(arg_ptr);
+      if (len < 0 || len >= (maxlen-5)) {
+         msg = realloc_pool_memory(msg, maxlen + maxlen/2);
+         continue;
+      }
+      break;
+   }
+   LogErrorMsg((const char *)msg);
+   free_memory(msg);
 }
 
 void
@@ -1045,21 +1172,27 @@ opendir(const char *path)
 {
     /* enough space for VSS !*/
     int max_len = strlen(path) + MAX_PATH;
+    char *tspec = NULL;
     _dir *rval = NULL;
     if (path == NULL) {
        errno = ENOENT;
        return NULL;
     }
 
-    Dmsg1(100, "Opendir path=%s\n", path);
+    Dmsg1(dbglvl, "Opendir path=%s\n", path);
     rval = (_dir *)malloc(sizeof(_dir));
+    if (!rval) {
+       goto err;
+    }
     memset (rval, 0, sizeof (_dir));
-    if (rval == NULL) return NULL;
-    char *tspec = (char *)malloc(max_len);
-    if (tspec == NULL) return NULL;
 
-    conv_unix_to_win32_path(path, tspec, max_len);
-    Dmsg1(100, "win32 path=%s\n", tspec);
+    tspec = (char *)malloc(max_len);
+    if (!tspec) { 
+       goto err;
+    }
+
+    conv_unix_to_vss_win32_path(path, tspec, max_len);
+    Dmsg1(dbglvl, "win32 path=%s\n", tspec);
 
     // add backslash only if there is none yet (think of c:\)
     if (tspec[strlen(tspec)-1] != '\\')
@@ -1088,7 +1221,7 @@ opendir(const char *path)
     } else goto err;
 
 
-    Dmsg3(99, "opendir(%s)\n\tspec=%s,\n\tFindFirstFile returns %d\n",
+    Dmsg3(dbglvl, "opendir(%s)\n\tspec=%s,\n\tFindFirstFile returns %d\n",
           path, rval->spec, rval->dirh);
 
     rval->offset = 0;
@@ -1096,18 +1229,22 @@ opendir(const char *path)
         goto err;
 
     if (rval->valid_w) {
-      Dmsg1(99, "\tFirstFile=%s\n", rval->data_w.cFileName);
+      Dmsg1(dbglvl, "\tFirstFile=%s\n", rval->data_w.cFileName);
     }
 
     if (rval->valid_a) {
-      Dmsg1(99, "\tFirstFile=%s\n", rval->data_a.cFileName);
+      Dmsg1(dbglvl, "\tFirstFile=%s\n", rval->data_a.cFileName);
     }
 
     return (DIR *)rval;
 
 err:
-    free((void *)rval->spec);
-    free(rval);
+    if (rval) {
+       free(rval);
+    }
+    if (tspec) {
+       free(tspec);
+    }
     errno = b_errno_win32;
     return NULL;
 }
@@ -1168,10 +1305,10 @@ readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
       }
 
       *result = entry;              /* return entry address */
-      Dmsg4(99, "readdir_r(%p, { d_name=\"%s\", d_reclen=%d, d_off=%d\n",
+      Dmsg4(dbglvl, "readdir_r(%p, { d_name=\"%s\", d_reclen=%d, d_off=%d\n",
             dirp, entry->d_name, entry->d_reclen, entry->d_off);
     } else {
-//      Dmsg0(99, "readdir_r !valid\n");
+//      Dmsg0(dbglvl, "readdir_r !valid\n");
         errno = b_errno_win32;
         return -1;
     }
@@ -1280,6 +1417,68 @@ WSA_Init(void)
     return 0;
 }
 
+static DWORD fill_attribute(DWORD attr, mode_t mode)
+{
+   Dmsg1(dbglvl, "  before attr=%lld\n", (uint64_t) attr);
+   /* Use Bacula mappings define in stat() above */
+   if (mode & (S_IRUSR|S_IRGRP|S_IROTH)) { // If file is readable
+      attr &= ~FILE_ATTRIBUTE_READONLY;    // then this is not READONLY
+   } else {
+      attr |= FILE_ATTRIBUTE_READONLY;
+   }
+   if (mode & S_ISVTX) {                   // The sticky bit <=> HIDDEN 
+      attr |= FILE_ATTRIBUTE_HIDDEN;
+   } else {
+      attr &= ~FILE_ATTRIBUTE_HIDDEN;
+   }
+   if (mode & S_IRWXO) {              // Other can read/write/execute ?
+      attr &= ~FILE_ATTRIBUTE_SYSTEM; // => Not system
+   } else {
+      attr |= FILE_ATTRIBUTE_SYSTEM;
+   }
+   Dmsg1(dbglvl, "  after attr=%lld\n", (uint64_t)attr);
+   return attr;
+}
+
+int win32_chmod(const char *path, mode_t mode)
+{
+   bool ret=false;
+   DWORD attr;
+
+   Dmsg2(dbglvl, "win32_chmod(path=%s mode=%lld)\n", path, (uint64_t)mode);
+   if (p_GetFileAttributesW) {
+      POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
+      make_win32_path_UTF8_2_wchar(&pwszBuf, path);
+
+      attr = p_GetFileAttributesW((LPCWSTR) pwszBuf);
+      if (attr != INVALID_FILE_ATTRIBUTES) {
+         /* Use Bacula mappings define in stat() above */
+         attr = fill_attribute(attr, mode);
+         ret = p_SetFileAttributesW((LPCWSTR)pwszBuf, attr);
+      }
+      free_pool_memory(pwszBuf);
+      Dmsg0(dbglvl, "Leave win32_chmod. AttributesW\n");
+   } else if (p_GetFileAttributesA) {
+      attr = p_GetFileAttributesA(path);
+      if (attr != INVALID_FILE_ATTRIBUTES) {
+         attr = fill_attribute(attr, mode);
+         ret = p_SetFileAttributesA(path, attr);
+      }
+      Dmsg0(dbglvl, "Leave win32_chmod did AttributesA\n");
+   } else {
+      Dmsg0(dbglvl, "Leave win32_chmod did nothing\n");
+   }
+    
+   if (!ret) {
+      const char *err = errorString();
+      Dmsg2(dbglvl, "Get/SetFileAttributes(%s): %s\n", path, err);
+      LocalFree((void *)err);
+      errno = b_errno_win32;
+      return -1;
+   }
+   return 0;
+}
+
 
 int
 win32_chdir(const char *dir)
@@ -1296,14 +1495,14 @@ win32_chdir(const char *dir)
          errno = b_errno_win32;
          return -1;
       }
-   }
-   else if (p_SetCurrentDirectoryA) {
+   } else if (p_SetCurrentDirectoryA) {
       if (0 == p_SetCurrentDirectoryA(dir)) {
          errno = b_errno_win32;
          return -1;
       }
+   } else {
+      return -1;
    }
-   else return -1;
 
    return 0;
 }
@@ -1311,15 +1510,18 @@ win32_chdir(const char *dir)
 int
 win32_mkdir(const char *dir)
 {
+   Dmsg1(dbglvl, "enter win32_mkdir. dir=%s\n", dir);
    if (p_wmkdir){
       POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
       make_win32_path_UTF8_2_wchar(&pwszBuf, dir);
 
       int n = p_wmkdir((LPCWSTR)pwszBuf);
       free_pool_memory(pwszBuf);
+      Dmsg0(dbglvl, "Leave win32_mkdir did wmkdir\n");
       return n;
    }
 
+   Dmsg0(dbglvl, "Leave win32_mkdir did _mkdir\n");
    return _mkdir(dir);
 }
 
@@ -1462,8 +1664,10 @@ win32_unlink(const char *filename)
 
       nRetCode = _wunlink((LPCWSTR) pwszBuf);
 
-      /* special case if file is readonly,
-      we retry but unset attribute before */
+      /*
+       * special case if file is readonly,
+       * we retry but unset attribute before
+       */
       if (nRetCode == -1 && errno == EACCES && p_SetFileAttributesW && p_GetFileAttributesW) {
          DWORD dwAttr =  p_GetFileAttributesW((LPCWSTR)pwszBuf);
          if (dwAttr != INVALID_FILE_ATTRIBUTES) {
@@ -1771,6 +1975,96 @@ GetApplicationName(const char *cmdline, char **pexe, const char **pargs)
    return true;
 }
 
+/**
+ * Create the process with WCHAR API
+ */
+static BOOL
+CreateChildProcessW(const char *comspec, const char *cmdLine,
+                    PROCESS_INFORMATION *hProcInfo,
+                    HANDLE in, HANDLE out, HANDLE err)
+{
+   STARTUPINFOW siStartInfo;
+   BOOL bFuncRetn = FALSE;
+
+   // Set up members of the STARTUPINFO structure.
+   ZeroMemory( &siStartInfo, sizeof(siStartInfo) );
+   siStartInfo.cb = sizeof(siStartInfo);
+   // setup new process to use supplied handles for stdin,stdout,stderr
+
+   siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
+   siStartInfo.wShowWindow = SW_SHOWMINNOACTIVE;
+
+   siStartInfo.hStdInput = in;
+   siStartInfo.hStdOutput = out;
+   siStartInfo.hStdError = err;
+   
+   // Convert argument to WCHAR
+   POOLMEM *cmdLine_wchar = get_pool_memory(PM_FNAME);
+   POOLMEM *comspec_wchar = get_pool_memory(PM_FNAME);
+
+   UTF8_2_wchar(&cmdLine_wchar, cmdLine);
+   UTF8_2_wchar(&comspec_wchar, comspec);
+
+   // Create the child process.
+   Dmsg2(dbglvl, "Calling CreateProcess(%s, %s, ...)\n", comspec_wchar, cmdLine_wchar);
+
+   // try to execute program
+   bFuncRetn = p_CreateProcessW((WCHAR*)comspec_wchar,
+                                (WCHAR*)cmdLine_wchar,// command line
+                                NULL,      // process security attributes
+                                NULL,      // primary thread security attributes
+                                TRUE,      // handles are inherited
+                                0,         // creation flags
+                                NULL,      // use parent's environment
+                                NULL,      // use parent's current directory
+                                &siStartInfo,  // STARTUPINFO pointer
+                                hProcInfo);   // receives PROCESS_INFORMATION
+   free_pool_memory(cmdLine_wchar);
+   free_pool_memory(comspec_wchar);
+
+   return bFuncRetn;
+}
+
+
+/**
+ * Create the process with ANSI API
+ */
+static BOOL
+CreateChildProcessA(const char *comspec, char *cmdLine,
+                    PROCESS_INFORMATION *hProcInfo,
+                    HANDLE in, HANDLE out, HANDLE err)
+{
+   STARTUPINFOA siStartInfo;
+   BOOL bFuncRetn = FALSE;
+
+   // Set up members of the STARTUPINFO structure.
+   ZeroMemory( &siStartInfo, sizeof(siStartInfo) );
+   siStartInfo.cb = sizeof(siStartInfo);
+   // setup new process to use supplied handles for stdin,stdout,stderr
+   siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
+   siStartInfo.wShowWindow = SW_SHOWMINNOACTIVE;
+
+   siStartInfo.hStdInput = in;
+   siStartInfo.hStdOutput = out;
+   siStartInfo.hStdError = err;
+
+   // Create the child process.
+   Dmsg2(dbglvl, "Calling CreateProcess(%s, %s, ...)\n", comspec, cmdLine);
+
+   // try to execute program
+   bFuncRetn = p_CreateProcessA(comspec,
+                                cmdLine,  // command line
+                                NULL,     // process security attributes
+                                NULL,     // primary thread security attributes
+                                TRUE,     // handles are inherited
+                                0,        // creation flags
+                                NULL,     // use parent's environment
+                                NULL,     // use parent's current directory
+                                &siStartInfo,// STARTUPINFO pointer
+                                hProcInfo);// receives PROCESS_INFORMATION
+   return bFuncRetn;
+}
+
 /**
  * OK, so it would seem CreateProcess only handles true executables:
  * .com or .exe files.  So grab $COMSPEC value and pass command line to it.
@@ -1780,43 +2074,29 @@ CreateChildProcess(const char *cmdline, HANDLE in, HANDLE out, HANDLE err)
 {
    static const char *comspec = NULL;
    PROCESS_INFORMATION piProcInfo;
-   STARTUPINFOA siStartInfo;
    BOOL bFuncRetn = FALSE;
 
-   if (comspec == NULL) {
+   if (!p_CreateProcessA || !p_CreateProcessW)
+      return INVALID_HANDLE_VALUE;
+
+   if (comspec == NULL) 
       comspec = getenv("COMSPEC");
-   }
    if (comspec == NULL) // should never happen
       return INVALID_HANDLE_VALUE;
 
    // Set up members of the PROCESS_INFORMATION structure.
    ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
 
-   // Set up members of the STARTUPINFO structure.
-
-   ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
-   siStartInfo.cb = sizeof(STARTUPINFO);
-   // setup new process to use supplied handles for stdin,stdout,stderr
    // if supplied handles are not used the send a copy of our STD_HANDLE
    // as appropriate
-   siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
-   siStartInfo.wShowWindow = SW_SHOWMINNOACTIVE;
+   if (in == INVALID_HANDLE_VALUE)
+      in = GetStdHandle(STD_INPUT_HANDLE);
 
-   if (in != INVALID_HANDLE_VALUE)
-      siStartInfo.hStdInput = in;
-   else
-      siStartInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
+   if (out == INVALID_HANDLE_VALUE)
+      out = GetStdHandle(STD_OUTPUT_HANDLE);
 
-   if (out != INVALID_HANDLE_VALUE)
-      siStartInfo.hStdOutput = out;
-   else
-      siStartInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
-   if (err != INVALID_HANDLE_VALUE)
-      siStartInfo.hStdError = err;
-   else
-      siStartInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
-
-   // Create the child process.
+   if (err == INVALID_HANDLE_VALUE)
+      err = GetStdHandle(STD_ERROR_HANDLE);
 
    char *exeFile;
    const char *argStart;
@@ -1825,43 +2105,33 @@ CreateChildProcess(const char *cmdline, HANDLE in, HANDLE out, HANDLE err)
       return INVALID_HANDLE_VALUE;
    }
 
-   int cmdLen = strlen(comspec) + 4 + strlen(exeFile) + strlen(argStart) + 1;
-
-   char *cmdLine = (char *)alloca(cmdLen);
-
-   snprintf(cmdLine, cmdLen, "%s /c %s%s", comspec, exeFile, argStart);
+   POOL_MEM cmdLine(PM_FNAME);
+   Mmsg(cmdLine, "%s /c %s%s", comspec, exeFile, argStart);
 
    free(exeFile);
 
-   Dmsg2(150, "Calling CreateProcess(%s, %s, ...)\n", comspec, cmdLine);
-
-   // try to execute program
-   bFuncRetn = CreateProcessA(comspec,
-                              cmdLine,       // command line
-                              NULL,          // process security attributes
-                              NULL,          // primary thread security attributes
-                              TRUE,          // handles are inherited
-                              0,             // creation flags
-                              NULL,          // use parent's environment
-                              NULL,          // use parent's current directory
-                              &siStartInfo,  // STARTUPINFO pointer
-                              &piProcInfo);  // receives PROCESS_INFORMATION
+   // New function disabled
+   if (p_CreateProcessW && p_MultiByteToWideChar) {
+      bFuncRetn = CreateChildProcessW(comspec, cmdLine.c_str(), &piProcInfo,
+                                      in, out, err);
+   } else {
+      bFuncRetn = CreateChildProcessA(comspec, cmdLine.c_str(), &piProcInfo,
+                                      in, out, err);
+   }
 
    if (bFuncRetn == 0) {
       ErrorExit("CreateProcess failed\n");
       const char *err = errorString();
-      Dmsg3(99, "CreateProcess(%s, %s, ...)=%s\n", comspec, cmdLine, err);
+      Dmsg3(dbglvl, "CreateProcess(%s, %s, ...)=%s\n",comspec,cmdLine.c_str(),err);
       LocalFree((void *)err);
       return INVALID_HANDLE_VALUE;
    }
    // we don't need a handle on the process primary thread so we close
    // this now.
    CloseHandle(piProcInfo.hThread);
-
    return piProcInfo.hProcess;
 }
 
-
 void
 ErrorExit (LPCSTR lpszMessage)
 {
@@ -1979,7 +2249,7 @@ open_bpipe(char *prog, int wait, const char *mode)
                                      // process terminates we can
                                      // detect eof.
         // ugly but convert WIN32 HANDLE to FILE*
-        int rfd = _open_osfhandle((long)hChildStdoutRdDup, O_RDONLY | O_BINARY);
+        int rfd = _open_osfhandle((intptr_t)hChildStdoutRdDup, O_RDONLY | O_BINARY);
         if (rfd >= 0) {
            bpipe->rfd = _fdopen(rfd, "rb");
         }
@@ -1988,7 +2258,7 @@ open_bpipe(char *prog, int wait, const char *mode)
         CloseHandle(hChildStdinRd); // close our read side so as not
                                     // to interfre with child's copy
         // ugly but convert WIN32 HANDLE to FILE*
-        int wfd = _open_osfhandle((long)hChildStdinWrDup, O_WRONLY | O_BINARY);
+        int wfd = _open_osfhandle((intptr_t)hChildStdinWrDup, O_WRONLY | O_BINARY);
         if (wfd >= 0) {
            bpipe->wfd = _fdopen(wfd, "wb");
         }
@@ -2050,7 +2320,7 @@ close_bpipe(BPIPE *bpipe)
       if (!GetExitCodeProcess((HANDLE)bpipe->worker_pid, &exitCode)) {
          const char *err = errorString();
          rval = b_errno_win32;
-         Dmsg1(0, "GetExitCode error %s\n", err);
+         Dmsg1(dbglvl, "GetExitCode error %s\n", err);
          LocalFree((void *)err);
          break;
       }
@@ -2094,15 +2364,14 @@ close_wpipe(BPIPE *bpipe)
     return result;
 }
 
-#include "findlib/find.h"
-
+#ifndef MINGW64
 int
 utime(const char *fname, struct utimbuf *times)
 {
     FILETIME acc, mod;
     char tmpbuf[5000];
 
-    conv_unix_to_win32_path(fname, tmpbuf, 5000);
+    conv_unix_to_vss_win32_path(fname, tmpbuf, 5000);
 
     cvt_utime_to_ftime(times->actime, acc);
     cvt_utime_to_ftime(times->modtime, mod);
@@ -2110,10 +2379,10 @@ utime(const char *fname, struct utimbuf *times)
     HANDLE h = INVALID_HANDLE_VALUE;
 
     if (p_CreateFileW) {
-      POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
-      make_win32_path_UTF8_2_wchar(&pwszBuf, tmpbuf);
+       POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
+       make_win32_path_UTF8_2_wchar(&pwszBuf, tmpbuf);
 
-      h = p_CreateFileW((LPCWSTR)pwszBuf,
+       h = p_CreateFileW((LPCWSTR)pwszBuf,
                         FILE_WRITE_ATTRIBUTES,
                         FILE_SHARE_WRITE|FILE_SHARE_READ|FILE_SHARE_DELETE,
                         NULL,
@@ -2121,9 +2390,9 @@ utime(const char *fname, struct utimbuf *times)
                         FILE_FLAG_BACKUP_SEMANTICS, // required for directories
                         NULL);
 
-      free_pool_memory(pwszBuf);
+       free_pool_memory(pwszBuf);
     } else if (p_CreateFileA) {
-      h = p_CreateFileA(tmpbuf,
+       h = p_CreateFileA(tmpbuf,
                         FILE_WRITE_ATTRIBUTES,
                         FILE_SHARE_WRITE|FILE_SHARE_READ|FILE_SHARE_DELETE,
                         NULL,
@@ -2133,11 +2402,11 @@ utime(const char *fname, struct utimbuf *times)
     }
 
     if (h == INVALID_HANDLE_VALUE) {
-        const char *err = errorString();
-        Dmsg2(99, "Cannot open file \"%s\" for utime(): ERR=%s", tmpbuf, err);
-        LocalFree((void *)err);
-        errno = b_errno_win32;
-        return -1;
+       const char *err = errorString();
+       Dmsg2(dbglvl, "Cannot open file \"%s\" for utime(): ERR=%s", tmpbuf, err);
+       LocalFree((void *)err);
+       errno = b_errno_win32;
+       return -1;
     }
 
     int rval = SetFileTime(h, NULL, &acc, &mod) ? 0 : -1;
@@ -2147,54 +2416,55 @@ utime(const char *fname, struct utimbuf *times)
     }
     return rval;
 }
+#endif
 
 #if 0
 int
 file_open(const char *file, int flags, int mode)
 {
-    DWORD access = 0;
-    DWORD shareMode = 0;
-    DWORD create = 0;
-    DWORD msflags = 0;
-    HANDLE foo = INVALID_HANDLE_VALUE;
-    const char *remap = file;
-
-    if (flags & O_WRONLY) access = GENERIC_WRITE;
-    else if (flags & O_RDWR) access = GENERIC_READ|GENERIC_WRITE;
-    else access = GENERIC_READ;
-
-    if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
-       create = CREATE_NEW;
-    else if ((flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
-       create = CREATE_ALWAYS;
-    else if (flags & O_CREAT)
-       create = OPEN_ALWAYS;
-    else if (flags & O_TRUNC)
-       create = TRUNCATE_EXISTING;
-    else 
-       create = OPEN_EXISTING;
-
-    shareMode = 0;
-
-    if (flags & O_APPEND) {
-        printf("open...APPEND not implemented yet.");
-        exit(-1);
-    }
+   DWORD access = 0;
+   DWORD shareMode = 0;
+   DWORD create = 0;
+   DWORD msflags = 0;
+   HANDLE foo = INVALID_HANDLE_VALUE;
+   const char *remap = file;
+
+   if (flags & O_WRONLY) access = GENERIC_WRITE;
+   else if (flags & O_RDWR) access = GENERIC_READ|GENERIC_WRITE;
+   else access = GENERIC_READ;
+
+   if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+      create = CREATE_NEW;
+   else if ((flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
+      create = CREATE_ALWAYS;
+   else if (flags & O_CREAT)
+      create = OPEN_ALWAYS;
+   else if (flags & O_TRUNC)
+      create = TRUNCATE_EXISTING;
+   else 
+      create = OPEN_EXISTING;
+
+   shareMode = 0;
+
+   if (flags & O_APPEND) {
+      printf("open...APPEND not implemented yet.");
+      exit(-1);
+   }
 
-    if (p_CreateFileW) {
-       POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
-       make_win32_path_UTF8_2_wchar(&pwszBuf, file);
+   if (p_CreateFileW) {
+      POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
+      make_win32_path_UTF8_2_wchar(&pwszBuf, file);
 
-       foo = p_CreateFileW((LPCWSTR) pwszBuf, access, shareMode, NULL, create, msflags, NULL);
-       free_pool_memory(pwszBuf);
-    } else if (p_CreateFileA)
-       foo = CreateFile(file, access, shareMode, NULL, create, msflags, NULL);
+      foo = p_CreateFileW((LPCWSTR) pwszBuf, access, shareMode, NULL, create, msflags, NULL);
+      free_pool_memory(pwszBuf);
+   } else if (p_CreateFileA)
+      foo = CreateFile(file, access, shareMode, NULL, create, msflags, NULL);
 
-    if (INVALID_HANDLE_VALUE == foo) {
-        errno = b_errno_win32;
-        return(int) -1;
-    }
-    return (int)foo;
+   if (INVALID_HANDLE_VALUE == foo) {
+      errno = b_errno_win32;
+      return (int)-1;
+   }
+   return (int)foo;
 
 }
 
@@ -2274,7 +2544,98 @@ file_dup2(int, int)
 }
 #endif
 
+#ifdef xxx
+/* 
+ * Emulation of mmap and unmmap for tokyo dbm
+ */
+void *mmap(void *start, size_t length, int prot, int flags,
+           int fd, off_t offset)
+{
+   DWORD fm_access = 0;
+   DWORD mv_access = 0;
+   HANDLE h;
+   HANDLE mv;
+
+   if (length == 0) {
+      return MAP_FAILED;
+   }
+   if (!fd) {
+      return MAP_FAILED;
+   }
+
+   if (flags & PROT_WRITE) {
+      fm_access |= PAGE_READWRITE;
+   } else if (flags & PROT_READ) {
+      fm_access |= PAGE_READONLY;
+   }
+   
+   if (flags & PROT_READ) {
+      mv_access |= FILE_MAP_READ;
+   }
+   if (flags & PROT_WRITE) {
+      mv_access |= FILE_MAP_WRITE;
+   }
+
+   h = CreateFileMapping((HANDLE)_get_osfhandle (fd), 
+                         NULL /* security */, 
+                         fm_access, 
+                         0 /* MaximumSizeHigh */, 
+                         0 /* MaximumSizeLow */, 
+                         NULL /* name of the file mapping object */);
+
+   if (!h || h == INVALID_HANDLE_VALUE) {
+      return MAP_FAILED;
+   }
+
+   mv = MapViewOfFile(h, mv_access, 
+                      0 /* offset hi */, 
+                      0 /* offset lo */,
+                      length);
+   CloseHandle(h);
+
+   if (!mv || mv == INVALID_HANDLE_VALUE) {
+      return MAP_FAILED;
+   }
+
+   return (void *) mv;
+}
+
+int munmap(void *start, size_t length)
+{
+   if (!start) {
+      return -1;
+   }
+   UnmapViewOfFile(start);
+   return 0;
+}
+#endif
+
 #ifdef HAVE_MINGW
 /* syslog function, added by Nicolas Boichat */
 void openlog(const char *ident, int option, int facility) {}  
 #endif //HAVE_MINGW
+
+/* Log an error message */
+void LogErrorMsg(const char *message)
+{
+   HANDLE eventHandler;
+   const char *strings[2];
+
+   /* Use the OS event logging to log the error */
+   eventHandler = RegisterEventSource(NULL, "Bacula");
+
+   strings[0] = _("\n\nBacula ERROR: ");
+   strings[1] = message;
+
+   if (eventHandler) {
+      ReportEvent(eventHandler, EVENTLOG_ERROR_TYPE,
+              0,                      /* category */
+              0,                      /* ID */
+              NULL,                   /* SID */
+              2,                      /* Number of strings */
+              0,                      /* raw data size */
+              (const char **)strings, /* error strings */
+              NULL);                  /* raw data */
+      DeregisterEventSource(eventHandler);
+   }
+}