#define USE_WIN32_COMPAT_IO 1
+#define USE_WIN32_32KPATHCONVERSION 1
 
 extern void d_msg(const char *file, int line, int level, const char *fmt,...);
 extern DWORD   g_platform_id;
 #endif
 }
 
+POOLMEM* 
+make_wchar_win32_path(POOLMEM* pszUCSPath, BOOL* pBIsRawPath /*= NULL*/)
+{
+   /* created 02/27/2006 Thorsten Engel
+      
+      This function expects an UCS-encoded standard WCHAR 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 */
+
+   if (pBIsRawPath)
+      *pBIsRawPath = FALSE;
+
+   if (!p_GetCurrentDirectoryW)
+      return pszUCSPath;
+   
+   WCHAR* name = (WCHAR*) pszUCSPath;
+
+   /* if it has already the desired form, exit without changes */
+   if (wcslen(name) > 3 && wcsncmp (name, L"\\\\?\\", 4) == 0)
+      return pszUCSPath;
+
+   POOLMEM* pwszBuf = get_pool_memory (PM_FNAME);
+   POOLMEM* pwszCurDirBuf = get_pool_memory (PM_FNAME);
+   DWORD dwCurDirPathSize = 0;
+
+   /* get buffer with enough size (name+max 6. wchars+1 null terminator */
+   DWORD dwBufCharsNeeded = (wcslen(name)+7);
+   pwszBuf = check_pool_memory_size(pwszBuf, dwBufCharsNeeded*sizeof(WCHAR));
+      
+   /* add \\?\ to support 32K long filepaths 
+      it is important to make absolute paths, so we add drive and
+      current path if necessary */
+
+   BOOL bAddDrive = TRUE;
+   BOOL bAddCurrentPath = TRUE;
+   BOOL bAddPrefix = TRUE;
+
+   /* does path begin with drive? if yes, it is absolute */
+   if (wcslen(name) > 3 && (iswalpha (*name) && *(name+1) == ':'
+       && (*(name+2) == '\\' || *(name+2) == '/'))) {
+      bAddDrive = FALSE;
+      bAddCurrentPath = FALSE;
+   }
+
+   /* is path absolute? */
+   if (*name == '/' || *name == '\\')
+      bAddCurrentPath = FALSE; 
+
+   /* is path relative to itself?, if yes, skip ./ */
+   if (wcslen(name) > 2 && ((wcsncmp (name, L"./", 2) == 0) || (wcsncmp (name, L".\\", 2) == 0))) {
+      name+=2;
+   }
+
+   /* is path of form '//./'? */   
+   if (wcslen(name) > 3 && ((wcsncmp (name, L"//./", 4) == 0) || (wcsncmp (name, L"\\\\.\\", 4) == 0))) {
+      bAddDrive = FALSE;
+      bAddCurrentPath = FALSE;
+      bAddPrefix = FALSE;
+      if (pBIsRawPath)
+         *pBIsRawPath = TRUE;
+   }
+
+   int nParseOffset = 0;
+   
+   /* add 4 bytes header */
+   if (bAddPrefix) {
+      nParseOffset = 4;
+      wcscpy ((WCHAR*) pwszBuf,L"\\\\?\\");
+   }
+
+   /* get current path if needed */
+   if (bAddDrive || bAddCurrentPath) {
+      dwCurDirPathSize = p_GetCurrentDirectoryW(0, NULL);
+      if (dwCurDirPathSize > 0) {
+         /* get directory into own buffer as it may either return c:\... or \\?\C:\.... */         
+         pwszCurDirBuf = check_pool_memory_size(pwszCurDirBuf, (dwCurDirPathSize+1)*sizeof(WCHAR));
+         p_GetCurrentDirectoryW(dwCurDirPathSize,(WCHAR*)pwszCurDirBuf);
+      }
+      else
+      {
+         /* we have no info for doing so */
+         bAddDrive = FALSE;
+         bAddCurrentPath = FALSE;
+      }
+   }
+      
+
+   /* add drive if needed */
+   if (bAddDrive && !bAddCurrentPath) {
+      WCHAR szDrive[3];
+
+      if (dwCurDirPathSize > 3 && wcsncmp ((LPCWSTR)pwszCurDirBuf, L"\\\\?\\", 4) == 0)
+         /* copy drive character */
+         wcsncpy ((WCHAR*) szDrive, (LPCWSTR)pwszCurDirBuf+4,2);          
+      else
+         /* copy drive character */
+         wcsncpy ((WCHAR*) szDrive, (LPCWSTR)pwszCurDirBuf,2);  
+
+      szDrive[2] = 0;
+            
+      wcscat ((WCHAR*) pwszBuf, szDrive);  
+      nParseOffset +=2;
+   }
+
+   /* add path if needed */
+   if (bAddCurrentPath) {
+      /* the 1 add. character is for the eventually added backslash */
+      dwBufCharsNeeded += dwCurDirPathSize+1; 
+      pwszBuf = check_pool_memory_size(pwszBuf, dwBufCharsNeeded*sizeof(WCHAR));
+      /* get directory into own buffer as it may either return c:\... or \\?\C:\.... */
+      
+      if (dwCurDirPathSize > 3 && wcsncmp ((LPCWSTR)pwszCurDirBuf, L"\\\\?\\", 4) == 0)
+         /* copy complete string */
+         wcscpy ((WCHAR*) pwszBuf, (LPCWSTR)pwszCurDirBuf);          
+      else
+         /* append path  */
+         wcscat ((WCHAR*) pwszBuf, (LPCWSTR)pwszCurDirBuf);       
+
+      nParseOffset = wcslen ((LPCWSTR) pwszBuf);
+
+      /* check if path ends with backslash, if not, add one */
+      if (*((WCHAR*) pwszBuf+nParseOffset-1) != L'\\') {
+         wcscat ((WCHAR*) pwszBuf, L"\\");
+         nParseOffset++;
+      }      
+   }
+
+
+   WCHAR* win32_name = (WCHAR*) pwszBuf+nParseOffset;
+
+   while (*name) {
+      /* Check for Unix separator and convert to Win32 */
+      if (*name == '/') {
+         *win32_name++ = '\\';     /* convert char */
+         /* If Win32 separated that is "quoted", remove quote */
+/* HELPME (Thorsten Engel): I don't understand the following part
+   and it removes a backslash from e.g. "\\.\c:" which I need for 
+   RAW device access. So I took it out */
+/*      } else if (*name == '\\' && name[1] == '\\') {
+         *win32_name++ = '\\';
+         name++;  */                 /* skip first \ */ 
+      } else {
+         *win32_name++ = *name;    /* copy character */
+      }
+      name++;
+   }
+   
+   /* null terminate string */
+   *win32_name = 0;
+
+#ifdef WIN32_VSS
+   /* 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
+   */ 
+   if (g_pVSSClient && enable_vss && g_pVSSClient->IsInitialized()) {
+      /* is output buffer large enough? */
+      pwszBuf = check_pool_memory_size(pwszBuf, (dwBufCharsNeeded+MAX_PATH)*sizeof(WCHAR));
+      /* create temp. buffer */
+      POOLMEM* pszBuf = get_pool_memory (PM_FNAME);
+      pszBuf = check_pool_memory_size(pszBuf, (dwBufCharsNeeded+MAX_PATH)*sizeof(WCHAR));
+      if (bAddPrefix)
+         nParseOffset = 4;
+      else
+         nParseOffset = 0; 
+      wcsncpy  ((WCHAR*) pszBuf, (WCHAR*) pwszBuf+nParseOffset, wcslen((WCHAR*)pwszBuf)+1-nParseOffset);
+      g_pVSSClient->GetShadowPathW((WCHAR*)pszBuf,(WCHAR*)pwszBuf,dwBufCharsNeeded+MAX_PATH);
+      free_pool_memory(pszBuf);
+   }   
+#endif
+
+   free_pool_memory (pszUCSPath);
+   free_pool_memory (pwszCurDirBuf);
+
+   return pwszBuf;
+}
+
 int
 wchar_2_UTF8(char *pszUTF, const WCHAR *pszUCS, int cchChar)
 {
     }
 }
 
+int 
+make_win32_path_UTF8_2_wchar(POOLMEM **pszUCS, const char *pszUTF, BOOL* pBIsRawPath /*= NULL*/)
+{
+   /* helper to convert from utf-8 to UCS-2 and to complete a path for 32K path syntax */
+   int nRet = UTF8_2_wchar(pszUCS, pszUTF);
+
+#ifdef USE_WIN32_32KPATHCONVERSION
+   /* add \\?\ to support 32K long filepaths */
+   *pszUCS = make_wchar_win32_path(*pszUCS, pBIsRawPath);
+#else
+   if (pBIsRawPath)
+      *pBIsRawPath = FALSE;
+#endif
+
+   return nRet;
+}
+
 #ifndef HAVE_VC8
 int umask(int)
 {
    // use unicode or ascii
    if (p_FindFirstFileW) {
       POOLMEM* pwszBuf = get_pool_memory (PM_FNAME);
-      UTF8_2_wchar(&pwszBuf, file);
+      make_win32_path_UTF8_2_wchar(&pwszBuf, file);
 
       h = p_FindFirstFileW((LPCWSTR) pwszBuf, &info_w);
       free_pool_memory(pwszBuf);
 
     if (p_GetFileAttributesW) {
       POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
-      UTF8_2_wchar(&pwszBuf, tmpbuf);
+      make_win32_path_UTF8_2_wchar(&pwszBuf, tmpbuf);
 
       attr = p_GetFileAttributesW((LPCWSTR) pwszBuf);
       free_pool_memory(pwszBuf);
     if (attr == -1) {
         const char *err = errorString();
         d_msg(__FILE__, __LINE__, 99,
-              "GetFileAttrubtes(%s): %s\n", tmpbuf, err);
+              "GetFileAttributes(%s): %s\n", tmpbuf, err);
         LocalFree((void *)err);
         errno = b_errno_win32;
         return -1;
    if (p_GetFileAttributesExW) {
       /* dynamically allocate enough space for UCS2 filename */
       POOLMEM* pwszBuf = get_pool_memory (PM_FNAME);
-      UTF8_2_wchar(&pwszBuf, file);
+      make_win32_path_UTF8_2_wchar(&pwszBuf, file);
 
       BOOL b = p_GetFileAttributesExW((LPCWSTR) pwszBuf, GetFileExInfoStandard, &data);
       free_pool_memory(pwszBuf);
     // convert to WCHAR
     if (p_FindFirstFileW) {
       POOLMEM* pwcBuf = get_pool_memory(PM_FNAME);;
-      UTF8_2_wchar(&pwcBuf,rval->spec);
+      make_win32_path_UTF8_2_wchar(&pwcBuf,rval->spec);
+
       rval->dirh = p_FindFirstFileW((LPCWSTR)pwcBuf, &rval->data_w);
 
       free_pool_memory(pwcBuf);
 {
    if (p_SetCurrentDirectoryW) {
       POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
-      UTF8_2_wchar(&pwszBuf, dir);
+      make_win32_path_UTF8_2_wchar(&pwszBuf, dir);
 
       BOOL b=p_SetCurrentDirectoryW((LPCWSTR)pwszBuf);
+      
       free_pool_memory(pwszBuf);
 
       if (!b) {
 {
    if (p_wmkdir){
       POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
-      UTF8_2_wchar(&pwszBuf, dir);
+      make_win32_path_UTF8_2_wchar(&pwszBuf, dir);
 
       int n=p_wmkdir((LPCWSTR)pwszBuf);
       free_pool_memory(pwszBuf);
       pwszBuf = check_pool_memory_size (pwszBuf, maxlen*sizeof(WCHAR));
 
       n = p_GetCurrentDirectoryW(maxlen, (LPWSTR) pwszBuf);
-      n = wchar_2_UTF8 (buf, (WCHAR*)pwszBuf, maxlen)-1;
+      if (n!=0)
+         n = wchar_2_UTF8 (buf, (WCHAR*)pwszBuf, maxlen)-1;
       free_pool_memory(pwszBuf);
 
    } else if (p_GetCurrentDirectoryA)
    int nRetCode;
    if (p_wunlink) {
       POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
-      UTF8_2_wchar(&pwszBuf, filename);
+      make_win32_path_UTF8_2_wchar(&pwszBuf, filename);
+
       nRetCode = _wunlink((LPCWSTR) pwszBuf);
 
       /* special case if file is readonly,
 
     if (p_CreateFileW) {
       POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
-      UTF8_2_wchar(&pwszBuf, tmpbuf);
+      make_win32_path_UTF8_2_wchar(&pwszBuf, tmpbuf);
 
       h = p_CreateFileW((LPCWSTR) pwszBuf,
                         FILE_WRITE_ATTRIBUTES,
 {
    if (p_wopen) {
       POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
-      UTF8_2_wchar(&pwszBuf, file);
+      make_win32_path_UTF8_2_wchar(&pwszBuf, file);
 
       int nRet = p_wopen((LPCWSTR) pwszBuf, flags|_O_BINARY, mode);
       free_pool_memory(pwszBuf);
 
     if (p_CreateFileW) {
        POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
-       UTF8_2_wchar(pwszBuf, file);
+       make_win32_path_UTF8_2_wchar(pwszBuf, file);
 
        foo = p_CreateFileW((LPCWSTR) pwszBuf, access, shareMode, NULL, create, msflags, NULL);
        free_pool_memory(pwszBuf);