]> git.sur5r.net Git - bacula/bacula/commitdiff
take out 260char limit for win NT/XP, etc. paths can become 32K characters long now.
authorThorsten Engel <thorsten.engel@matrix-computer.com>
Tue, 28 Feb 2006 15:45:56 +0000 (15:45 +0000)
committerThorsten Engel <thorsten.engel@matrix-computer.com>
Tue, 28 Feb 2006 15:45:56 +0000 (15:45 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@2822 91ce42f0-d328-0410-95d8-f526ca767f89

bacula/src/filed/win32/winbacula.h
bacula/src/findlib/attribs.c
bacula/src/findlib/bfile.c
bacula/src/findlib/create_file.c
bacula/src/lib/winapi.h
bacula/src/win32/compat/compat.cpp
bacula/src/win32/compat/vss.cpp
bacula/src/win32/compat/vss.h

index ea33d26a50c95ee498414fb1d2da99925158c757..f56b9ed92b4906c417fcbd57528fe37248f3b8db 100755 (executable)
@@ -56,7 +56,7 @@ extern HINSTANCE        hAppInstance;
 extern const char       *szAppName;
 extern DWORD            mainthreadId;
 
-// Main UPS server routine
+// Main Bacula server routine
 extern int BaculaAppMain();
 
 extern void LogErrorMsg(char *msg);
index 3e4f7cd64c1f3eb1cb1e47a8fca7b5c373943175..fecbddb67dd1686de55f9a2a1dba9cb8888f2a04 100755 (executable)
@@ -512,12 +512,12 @@ int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt)
 
    attribsEx[0] = 0;                  /* no extended attributes */
 
+   unix_name_to_win32(&ff_pkt->sys_fname, ff_pkt->fname);
+
    // try unicode version
    if (p_GetFileAttributesExW)  {
-      unix_name_to_win32(&ff_pkt->sys_fname, ff_pkt->fname);
-
       POOLMEM* pwszBuf = get_pool_memory (PM_FNAME);   
-      UTF8_2_wchar(&pwszBuf, ff_pkt->sys_fname);
+      make_win32_path_UTF8_2_wchar(&pwszBuf, ff_pkt->fname);
 
       BOOL b=p_GetFileAttributesExW((LPCWSTR) pwszBuf, GetFileExInfoStandard, (LPVOID)&atts);
       free_pool_memory(pwszBuf);
@@ -529,9 +529,7 @@ int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt)
    }
    else {
       if (!p_GetFileAttributesExA)
-         return STREAM_UNIX_ATTRIBUTES;
-
-      unix_name_to_win32(&ff_pkt->sys_fname, ff_pkt->fname);
+         return STREAM_UNIX_ATTRIBUTES;      
 
       if (!p_GetFileAttributesExA(ff_pkt->sys_fname, GetFileExInfoStandard,
                               (LPVOID)&atts)) {
@@ -632,8 +630,6 @@ static bool set_win32_attributes(JCR *jcr, ATTR *attr, BFILE *ofd)
    win32_ofile = get_pool_memory(PM_FNAME);
    unix_name_to_win32(&win32_ofile, attr->ofname);
 
-
-
    /* At this point, we have reconstructed the WIN32_FILE_ATTRIBUTE_DATA pkt */
 
    if (!is_bopen(ofd)) {
@@ -657,7 +653,7 @@ static bool set_win32_attributes(JCR *jcr, ATTR *attr, BFILE *ofd)
    {
       if (p_SetFileAttributesW) {
          POOLMEM* pwszBuf = get_pool_memory (PM_FNAME);   
-         UTF8_2_wchar(&pwszBuf, win32_ofile);
+         make_win32_path_UTF8_2_wchar(&pwszBuf, attr->ofname);
 
          BOOL b=p_SetFileAttributesW((LPCWSTR)pwszBuf, atts.dwFileAttributes & SET_ATTRS);
          free_pool_memory(pwszBuf);
index 85b3ffe9e3b0dec4c75aebc0840934171b9db9eb..8f1321727af881daff4739f10baeda382c3a8eec 100644 (file)
@@ -386,7 +386,7 @@ int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
       return 0;
 
    if (p_CreateFileW && p_MultiByteToWideChar)               
-      UTF8_2_wchar(&win32_fname_wchar, win32_fname);
+      make_win32_path_UTF8_2_wchar(&win32_fname_wchar, fname);
 
    if (flags & O_CREAT) {             /* Create */
       if (bfd->use_backup_api) {
index 8f65b909613316c57d6cfe4cc141ed1d9345f145..0cea7be666d01ff8195e4a1a2c3a227e0bec56b3 100644 (file)
@@ -176,23 +176,36 @@ int create_file(JCR *jcr, ATTR *attr, BFILE *bfd, int replace)
             Qmsg1(jcr, M_ERROR, 0, _("bpkt already open fid=%d\n"), bfd->fid);
             bclose(bfd);
          }
+      
+
+         if ((bopen(bfd, attr->ofname, mode, S_IRUSR | S_IWUSR)) < 0) {
+            berrno be;
+            be.set_errno(bfd->berrno);
+            Qmsg2(jcr, M_ERROR, 0, _("Could not create %s: ERR=%s\n"),
+                  attr->ofname, be.strerror());
+            return CF_ERROR;
+         }
+
+         /* this doesn't solve the Microsoft problem - Thorsten Engel 
+            so I reused the code of V 1.40
          /*
           * If the open fails, we attempt to cd into the directory
           *  and create the file with a relative path rather than
           *  the full absolute path.  This is for Win32 where
           *  path names may be too long to create.
           */
+         /*
          if ((bopen(bfd, attr->ofname, mode, S_IRUSR | S_IWUSR)) < 0) {
             berrno be;
             int stat;
             Dmsg2(000, "bopen failed errno=%d: ERR=%s\n", bfd->berrno,  
-               be.strerror(bfd->berrno));
-            if (strlen(attr->ofname) > 250) {   /* Microsoft limitation */
+               be.strerror(bfd->berrno));            
+            if (strlen(attr->ofname) > 250) {   // Microsoft limitation 
                char savechr;
                char *p, *e;
                struct saved_cwd cwd;
                savechr = attr->ofname[pnl];
-               attr->ofname[pnl] = 0;                 /* terminate path */
+               attr->ofname[pnl] = 0;                 // terminate path 
                Dmsg1(000, "Do chdir %s\n", attr->ofname);
                if (save_cwd(&cwd) != 0) {
                   Qmsg0(jcr, M_ERROR, 0, _("Could not save_dirn"));
@@ -239,8 +252,8 @@ int create_file(JCR *jcr, ATTR *attr, BFILE *bfd, int replace)
             }
             Qmsg2(jcr, M_ERROR, 0, _("Could not create %s: ERR=%s\n"),
                   attr->ofname, be.strerror(bfd->berrno));
-            return CF_ERROR;
-         }
+            return CF_ERROR; 
+         }*/
          return CF_EXTRACT;
 #ifndef HAVE_WIN32  // none of these exists on MS Windows
       case FT_RAW:                    /* Bacula raw device e.g. /dev/sda1 */
index a138f04f470c29197e468e6cf981ea5df1e25861..42db9f3fcba95f087a641ec9bb28794cd3cf9d38 100644 (file)
@@ -51,7 +51,7 @@ typedef char POOLMEM;
 
 int wchar_2_UTF8(char *pszUTF, const WCHAR *pszUCS, int cchChar = MAX_PATH_UTF8);
 int UTF8_2_wchar(POOLMEM **pszUCS, const char *pszUTF);
-
+int make_win32_path_UTF8_2_wchar(POOLMEM **pszUCS, const char *pszUTF, BOOL* pBIsRawPath = NULL);
 
 /* In ADVAPI32.DLL */
 
index 4fc0e6b8743dae75b9d81ce5e132a302be49de87..70e6e53efa1888428776a62727fcdb1dc863958e 100644 (file)
@@ -34,6 +34,7 @@
 
 
 #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;
@@ -91,6 +92,188 @@ void conv_unix_to_win32_path(const char *name, char *win32_name, DWORD dwSize)
 #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)
 {
@@ -151,6 +334,23 @@ wchar_win32_path(const char *name, WCHAR *win32_name)
     }
 }
 
+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)
 {
@@ -272,7 +472,7 @@ statDir(const char *file, struct stat *sb)
    // 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);
@@ -339,7 +539,7 @@ stat2(const char *file, struct stat *sb)
 
     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);
@@ -350,7 +550,7 @@ stat2(const char *file, struct stat *sb)
     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;
@@ -433,7 +633,7 @@ stat(const char *file, struct stat *sb)
    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);
@@ -679,7 +879,8 @@ opendir(const char *path)
     // 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);
@@ -894,9 +1095,10 @@ win32_chdir(const char *dir)
 {
    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) {
@@ -920,7 +1122,7 @@ win32_mkdir(const char *dir)
 {
    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);
@@ -941,7 +1143,8 @@ win32_getcwd(char *buf, int maxlen)
       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)
@@ -1063,7 +1266,8 @@ win32_unlink(const char *filename)
    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,
@@ -1527,7 +1731,7 @@ utime(const char *fname, struct utimbuf *times)
 
     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,
@@ -1572,7 +1776,7 @@ open(const char *file, int flags, int mode)
 {
    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);
@@ -1653,7 +1857,7 @@ open(const char *file, int flags, int mode)
 
     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);
index 8234aad31794e88bcfc6bf0bcc77eef2c17dc3f5..4278a18acb5cfaac4982e5eafe9ee1b448315819 100644 (file)
@@ -143,6 +143,35 @@ BOOL VSSClient::GetShadowPath(const char *szFilePath, char *szShadowPath, int nB
    return FALSE;   
 }
 
+BOOL VSSClient::GetShadowPathW(const WCHAR *szFilePath, WCHAR *szShadowPath, int nBuflen)
+{
+   if (!m_bBackupIsInitialized)
+      return FALSE;
+
+   /* check for valid pathname */
+   BOOL bIsValidName;
+   
+   bIsValidName = wcslen(szFilePath) > 3;
+   if (bIsValidName)
+      bIsValidName &= iswalpha (szFilePath[0]) &&
+                      szFilePath[1]==':' && 
+                      szFilePath[2] == '\\';
+
+   if (bIsValidName) {
+      int nDriveIndex = towupper(szFilePath[0])-'A';
+      if (m_szShadowCopyName[nDriveIndex][0] != 0) {
+         wcsncpy(szShadowPath, CA2W(m_szShadowCopyName[nDriveIndex]), nBuflen);
+         nBuflen -= (int)strlen(m_szShadowCopyName[nDriveIndex]);
+         wcsncat(szShadowPath, szFilePath+2, nBuflen);
+         return TRUE;
+      }
+   }
+   
+   wcsncpy(szShadowPath,  szFilePath, nBuflen);
+   errno = EINVAL;
+   return FALSE;   
+}
+
 
 const size_t VSSClient::GetWriterCount()
 {
index 65ae9380eb08b0499b2cb7648d40c3f3409877ad..ec10bfd3e75d05890a2a0ea00b8b20e665d77b5f 100644 (file)
@@ -47,7 +47,8 @@ public:
     virtual BOOL CreateSnapshots(char* szDriveLetters) = 0;
     virtual BOOL CloseBackup() = 0;
     virtual const char* GetDriverName() = 0;
-    BOOL GetShadowPath (const char* szFilePath, char* szShadowPath, int nBuflen);
+    BOOL GetShadowPath  (const char* szFilePath, char* szShadowPath, int nBuflen);
+    BOOL GetShadowPathW (const WCHAR* szFilePath, WCHAR* szShadowPath, int nBuflen); /* nBuflen in characters */
 
     const size_t GetWriterCount();
     const char* GetWriterInfo(size_t nIndex);