tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

FileName.cpp (20545B)


      1 // Windows/FileName.cpp
      2 
      3 #include "StdAfx.h"
      4 
      5 #include "FileName.h"
      6 
      7 #ifndef _UNICODE
      8 extern bool g_IsNT;
      9 #endif
     10 
     11 namespace NWindows {
     12 namespace NFile {
     13 namespace NName {
     14 
     15 #define IS_SEPAR(c) IS_PATH_SEPAR(c)
     16 
     17 int FindSepar(const wchar_t *s) throw()
     18 {
     19  for (const wchar_t *p = s;; p++)
     20  {
     21    const wchar_t c = *p;
     22    if (c == 0)
     23      return -1;
     24    if (IS_SEPAR(c))
     25      return (int)(p - s);
     26  }
     27 }
     28 
     29 #ifndef USE_UNICODE_FSTRING
     30 int FindSepar(const FChar *s) throw()
     31 {
     32  for (const FChar *p = s;; p++)
     33  {
     34    const FChar c = *p;
     35    if (c == 0)
     36      return -1;
     37    if (IS_SEPAR(c))
     38      return (int)(p - s);
     39  }
     40 }
     41 #endif
     42 
     43 #ifndef USE_UNICODE_FSTRING
     44 void NormalizeDirPathPrefix(FString &dirPath)
     45 {
     46  if (dirPath.IsEmpty())
     47    return;
     48  if (!IsPathSepar(dirPath.Back()))
     49    dirPath.Add_PathSepar();
     50 }
     51 #endif
     52 
     53 void NormalizeDirPathPrefix(UString &dirPath)
     54 {
     55  if (dirPath.IsEmpty())
     56    return;
     57  if (!IsPathSepar(dirPath.Back()))
     58    dirPath.Add_PathSepar();
     59 }
     60 
     61 #define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z')
     62 
     63 bool IsDrivePath(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && IS_SEPAR(s[2]); }
     64 
     65 bool IsAltPathPrefix(CFSTR s) throw()
     66 {
     67  unsigned len = MyStringLen(s);
     68  if (len == 0)
     69    return false;
     70  if (s[len - 1] != ':')
     71    return false;
     72 
     73  #if defined(_WIN32) && !defined(UNDER_CE)
     74  if (IsDevicePath(s))
     75    return false;
     76  if (IsSuperPath(s))
     77  {
     78    s += kSuperPathPrefixSize;
     79    len -= kSuperPathPrefixSize;
     80  }
     81  if (len == 2 && IsDrivePath2(s))
     82    return false;
     83  #endif
     84 
     85  return true;
     86 }
     87 
     88 #if defined(_WIN32) && !defined(UNDER_CE)
     89 
     90 const char * const kSuperPathPrefix = "\\\\?\\";
     91 static const char * const kSuperUncPrefix = "\\\\?\\UNC\\";
     92 
     93 #define IS_DEVICE_PATH(s)          (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '.' && IS_SEPAR((s)[3]))
     94 #define IS_SUPER_PREFIX(s)         (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '?' && IS_SEPAR((s)[3]))
     95 #define IS_SUPER_OR_DEVICE_PATH(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && ((s)[2] == '?' || (s)[2] == '.') && IS_SEPAR((s)[3]))
     96 
     97 #define IS_UNC_WITH_SLASH(s) ( \
     98     ((s)[0] == 'U' || (s)[0] == 'u') \
     99  && ((s)[1] == 'N' || (s)[1] == 'n') \
    100  && ((s)[2] == 'C' || (s)[2] == 'c') \
    101  && IS_SEPAR((s)[3]))
    102 
    103 bool IsDevicePath(CFSTR s) throw()
    104 {
    105  #ifdef UNDER_CE
    106 
    107  s = s;
    108  return false;
    109  /*
    110  // actually we don't know the way to open device file in WinCE.
    111  unsigned len = MyStringLen(s);
    112  if (len < 5 || len > 5 || !IsString1PrefixedByString2(s, "DSK"))
    113    return false;
    114  if (s[4] != ':')
    115    return false;
    116  // for reading use SG_REQ sg; if (DeviceIoControl(dsk, IOCTL_DISK_READ));
    117  */
    118  
    119  #else
    120  
    121  if (!IS_DEVICE_PATH(s))
    122    return false;
    123  unsigned len = MyStringLen(s);
    124  if (len == 6 && s[5] == ':')
    125    return true;
    126  if (len < 18 || len > 22 || !IsString1PrefixedByString2(s + kDevicePathPrefixSize, "PhysicalDrive"))
    127    return false;
    128  for (unsigned i = 17; i < len; i++)
    129    if (s[i] < '0' || s[i] > '9')
    130      return false;
    131  return true;
    132  
    133  #endif
    134 }
    135 
    136 bool IsSuperUncPath(CFSTR s) throw() { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); }
    137 bool IsNetworkPath(CFSTR s) throw()
    138 {
    139  if (!IS_SEPAR(s[0]) || !IS_SEPAR(s[1]))
    140    return false;
    141  if (IsSuperUncPath(s))
    142    return true;
    143  FChar c = s[2];
    144  return (c != '.' && c != '?');
    145 }
    146 
    147 unsigned GetNetworkServerPrefixSize(CFSTR s) throw()
    148 {
    149  if (!IS_SEPAR(s[0]) || !IS_SEPAR(s[1]))
    150    return 0;
    151  unsigned prefixSize = 2;
    152  if (IsSuperUncPath(s))
    153    prefixSize = kSuperUncPathPrefixSize;
    154  else
    155  {
    156    FChar c = s[2];
    157    if (c == '.' || c == '?')
    158      return 0;
    159  }
    160  int pos = FindSepar(s + prefixSize);
    161  if (pos < 0)
    162    return 0;
    163  return prefixSize + pos + 1;
    164 }
    165 
    166 bool IsNetworkShareRootPath(CFSTR s) throw()
    167 {
    168  unsigned prefixSize = GetNetworkServerPrefixSize(s);
    169  if (prefixSize == 0)
    170    return false;
    171  s += prefixSize;
    172  int pos = FindSepar(s);
    173  if (pos < 0)
    174    return true;
    175  return s[(unsigned)pos + 1] == 0;
    176 }
    177 
    178 static const unsigned kDrivePrefixSize = 3; /* c:\ */
    179 
    180 bool IsDrivePath2(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':'; }
    181 // bool IsDriveName2(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == 0; }
    182 bool IsSuperPath(const wchar_t *s) throw() { return IS_SUPER_PREFIX(s); }
    183 bool IsSuperOrDevicePath(const wchar_t *s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); }
    184 // bool IsSuperUncPath(const wchar_t *s) throw() { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); }
    185 
    186 #ifndef USE_UNICODE_FSTRING
    187 bool IsDrivePath2(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':'; }
    188 // bool IsDriveName2(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == 0; }
    189 bool IsDrivePath(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && IS_SEPAR(s[2]); }
    190 bool IsSuperPath(CFSTR s) throw() { return IS_SUPER_PREFIX(s); }
    191 bool IsSuperOrDevicePath(CFSTR s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); }
    192 #endif // USE_UNICODE_FSTRING
    193 
    194 bool IsDrivePath_SuperAllowed(CFSTR s) throw()
    195 {
    196  if (IsSuperPath(s))
    197    s += kSuperPathPrefixSize;
    198  return IsDrivePath(s);
    199 }
    200 
    201 bool IsDriveRootPath_SuperAllowed(CFSTR s) throw()
    202 {
    203  if (IsSuperPath(s))
    204    s += kSuperPathPrefixSize;
    205  return IsDrivePath(s) && s[kDrivePrefixSize] == 0;
    206 }
    207 
    208 bool IsAbsolutePath(const wchar_t *s) throw()
    209 {
    210  return IS_SEPAR(s[0]) || IsDrivePath2(s);
    211 }
    212 
    213 int FindAltStreamColon(CFSTR path) throw()
    214 {
    215  unsigned i = 0;
    216  if (IsDrivePath2(path))
    217    i = 2;
    218  int colonPos = -1;
    219  for (;; i++)
    220  {
    221    FChar c = path[i];
    222    if (c == 0)
    223      return colonPos;
    224    if (c == ':')
    225    {
    226      if (colonPos < 0)
    227        colonPos = i;
    228      continue;
    229    }
    230    if (IS_SEPAR(c))
    231      colonPos = -1;
    232  }
    233 }
    234 
    235 #ifndef USE_UNICODE_FSTRING
    236 
    237 static unsigned GetRootPrefixSize_Of_NetworkPath(CFSTR s)
    238 {
    239  // Network path: we look "server\path\" as root prefix
    240  int pos = FindSepar(s);
    241  if (pos < 0)
    242    return 0;
    243  int pos2 = FindSepar(s + (unsigned)pos + 1);
    244  if (pos2 < 0)
    245    return 0;
    246  return pos + pos2 + 2;
    247 }
    248 
    249 static unsigned GetRootPrefixSize_Of_SimplePath(CFSTR s)
    250 {
    251  if (IsDrivePath(s))
    252    return kDrivePrefixSize;
    253  if (!IS_SEPAR(s[0]))
    254    return 0;
    255  if (s[1] == 0 || !IS_SEPAR(s[1]))
    256    return 1;
    257  unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2);
    258  return (size == 0) ? 0 : 2 + size;
    259 }
    260 
    261 static unsigned GetRootPrefixSize_Of_SuperPath(CFSTR s)
    262 {
    263  if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize))
    264  {
    265    unsigned size = GetRootPrefixSize_Of_NetworkPath(s + kSuperUncPathPrefixSize);
    266    return (size == 0) ? 0 : kSuperUncPathPrefixSize + size;
    267  }
    268  // we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\"
    269  int pos = FindSepar(s + kSuperPathPrefixSize);
    270  if (pos < 0)
    271    return 0;
    272  return kSuperPathPrefixSize + pos + 1;
    273 }
    274 
    275 unsigned GetRootPrefixSize(CFSTR s) throw()
    276 {
    277  if (IS_DEVICE_PATH(s))
    278    return kDevicePathPrefixSize;
    279  if (IsSuperPath(s))
    280    return GetRootPrefixSize_Of_SuperPath(s);
    281  return GetRootPrefixSize_Of_SimplePath(s);
    282 }
    283 
    284 #endif // USE_UNICODE_FSTRING
    285 
    286 static unsigned GetRootPrefixSize_Of_NetworkPath(const wchar_t *s) throw()
    287 {
    288  // Network path: we look "server\path\" as root prefix
    289  int pos = FindSepar(s);
    290  if (pos < 0)
    291    return 0;
    292  int pos2 = FindSepar(s + (unsigned)pos + 1);
    293  if (pos2 < 0)
    294    return 0;
    295  return pos + pos2 + 2;
    296 }
    297 
    298 static unsigned GetRootPrefixSize_Of_SimplePath(const wchar_t *s) throw()
    299 {
    300  if (IsDrivePath(s))
    301    return kDrivePrefixSize;
    302  if (!IS_SEPAR(s[0]))
    303    return 0;
    304  if (s[1] == 0 || !IS_SEPAR(s[1]))
    305    return 1;
    306  unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2);
    307  return (size == 0) ? 0 : 2 + size;
    308 }
    309 
    310 static unsigned GetRootPrefixSize_Of_SuperPath(const wchar_t *s) throw()
    311 {
    312  if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize))
    313  {
    314    unsigned size = GetRootPrefixSize_Of_NetworkPath(s + kSuperUncPathPrefixSize);
    315    return (size == 0) ? 0 : kSuperUncPathPrefixSize + size;
    316  }
    317  // we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\"
    318  int pos = FindSepar(s + kSuperPathPrefixSize);
    319  if (pos < 0)
    320    return 0;
    321  return kSuperPathPrefixSize + pos + 1;
    322 }
    323 
    324 unsigned GetRootPrefixSize(const wchar_t *s) throw()
    325 {
    326  if (IS_DEVICE_PATH(s))
    327    return kDevicePathPrefixSize;
    328  if (IsSuperPath(s))
    329    return GetRootPrefixSize_Of_SuperPath(s);
    330  return GetRootPrefixSize_Of_SimplePath(s);
    331 }
    332 
    333 #else // _WIN32
    334 
    335 bool IsAbsolutePath(const wchar_t *s) { return IS_SEPAR(s[0]); }
    336 
    337 #ifndef USE_UNICODE_FSTRING
    338 unsigned GetRootPrefixSize(CFSTR s) { return IS_SEPAR(s[0]) ? 1 : 0; }
    339 #endif
    340 unsigned GetRootPrefixSize(const wchar_t *s) { return IS_SEPAR(s[0]) ? 1 : 0; }
    341 
    342 #endif // _WIN32
    343 
    344 
    345 #ifndef UNDER_CE
    346 
    347 static bool GetCurDir(UString &path)
    348 {
    349  path.Empty();
    350  DWORD needLength;
    351  #ifndef _UNICODE
    352  if (!g_IsNT)
    353  {
    354    TCHAR s[MAX_PATH + 2];
    355    s[0] = 0;
    356    needLength = ::GetCurrentDirectory(MAX_PATH + 1, s);
    357    path = fs2us(fas2fs(s));
    358  }
    359  else
    360  #endif
    361  {
    362    WCHAR s[MAX_PATH + 2];
    363    s[0] = 0;
    364    needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, s);
    365    path = s;
    366  }
    367  return (needLength > 0 && needLength <= MAX_PATH);
    368 }
    369 
    370 static bool ResolveDotsFolders(UString &s)
    371 {
    372  #ifdef _WIN32
    373  // s.Replace(L'/', WCHAR_PATH_SEPARATOR);
    374  #endif
    375  
    376  for (unsigned i = 0;;)
    377  {
    378    const wchar_t c = s[i];
    379    if (c == 0)
    380      return true;
    381    if (c == '.' && (i == 0 || IS_SEPAR(s[i - 1])))
    382    {
    383      const wchar_t c1 = s[i + 1];
    384      if (c1 == '.')
    385      {
    386        const wchar_t c2 = s[i + 2];
    387        if (IS_SEPAR(c2) || c2 == 0)
    388        {
    389          if (i == 0)
    390            return false;
    391          int k = i - 2;
    392          i += 2;
    393          
    394          for (;; k--)
    395          {
    396            if (k < 0)
    397              return false;
    398            if (!IS_SEPAR(s[(unsigned)k]))
    399              break;
    400          }
    401 
    402          do
    403            k--;
    404          while (k >= 0 && !IS_SEPAR(s[(unsigned)k]));
    405          
    406          unsigned num;
    407          
    408          if (k >= 0)
    409          {
    410            num = i - k;
    411            i = k;
    412          }
    413          else
    414          {
    415            num = (c2 == 0 ? i : (i + 1));
    416            i = 0;
    417          }
    418          
    419          s.Delete(i, num);
    420          continue;
    421        }
    422      }
    423      else if (IS_SEPAR(c1) || c1 == 0)
    424      {
    425        unsigned num = 2;
    426        if (i != 0)
    427          i--;
    428        else if (c1 == 0)
    429          num = 1;
    430        s.Delete(i, num);
    431        continue;
    432      }
    433    }
    434 
    435    i++;
    436  }
    437 }
    438 
    439 #endif // UNDER_CE
    440 
    441 #define LONG_PATH_DOTS_FOLDERS_PARSING
    442 
    443 
    444 /*
    445 Windows (at least 64-bit XP) can't resolve "." or ".." in paths that start with SuperPrefix \\?\
    446 To solve that problem we check such path:
    447   - super path contains        "." or ".." - we use kSuperPathType_UseOnlySuper
    448   - super path doesn't contain "." or ".." - we use kSuperPathType_UseOnlyMain
    449 */
    450 #ifdef LONG_PATH_DOTS_FOLDERS_PARSING
    451 #ifndef UNDER_CE
    452 static bool AreThereDotsFolders(CFSTR s)
    453 {
    454  for (unsigned i = 0;; i++)
    455  {
    456    FChar c = s[i];
    457    if (c == 0)
    458      return false;
    459    if (c == '.' && (i == 0 || IS_SEPAR(s[i - 1])))
    460    {
    461      FChar c1 = s[i + 1];
    462      if (c1 == 0 || IS_SEPAR(c1) ||
    463          (c1 == '.' && (s[i + 2] == 0 || IS_SEPAR(s[i + 2]))))
    464        return true;
    465    }
    466  }
    467 }
    468 #endif
    469 #endif // LONG_PATH_DOTS_FOLDERS_PARSING
    470 
    471 #ifdef WIN_LONG_PATH
    472 
    473 /*
    474 Most of Windows versions have problems, if some file or dir name
    475 contains '.' or ' ' at the end of name (Bad Path).
    476 To solve that problem, we always use Super Path ("\\?\" prefix and full path)
    477 in such cases. Note that "." and ".." are not bad names.
    478 
    479 There are 3 cases:
    480  1) If the path is already Super Path, we use that path
    481  2) If the path is not Super Path :
    482     2.1) Bad Path;  we use only Super Path.
    483     2.2) Good Path; we use Main Path. If it fails, we use Super Path.
    484 
    485 NeedToUseOriginalPath returns:
    486    kSuperPathType_UseOnlyMain    : Super already
    487    kSuperPathType_UseOnlySuper    : not Super, Bad Path
    488    kSuperPathType_UseMainAndSuper : not Super, Good Path
    489 */
    490 
    491 int GetUseSuperPathType(CFSTR s) throw()
    492 {
    493  if (IsSuperOrDevicePath(s))
    494  {
    495    #ifdef LONG_PATH_DOTS_FOLDERS_PARSING
    496    if ((s)[2] != '.')
    497      if (AreThereDotsFolders(s + kSuperPathPrefixSize))
    498        return kSuperPathType_UseOnlySuper;
    499    #endif
    500    return kSuperPathType_UseOnlyMain;
    501  }
    502 
    503  for (unsigned i = 0;; i++)
    504  {
    505    FChar c = s[i];
    506    if (c == 0)
    507      return kSuperPathType_UseMainAndSuper;
    508    if (c == '.' || c == ' ')
    509    {
    510      FChar c2 = s[i + 1];
    511      if (c2 == 0 || IS_SEPAR(c2))
    512      {
    513        // if it's "." or "..", it's not bad name.
    514        if (c == '.')
    515        {
    516          if (i == 0 || IS_SEPAR(s[i - 1]))
    517            continue;
    518          if (s[i - 1] == '.')
    519          {
    520            if (i - 1 == 0 || IS_SEPAR(s[i - 2]))
    521              continue;
    522          }
    523        }
    524        return kSuperPathType_UseOnlySuper;
    525      }
    526    }
    527  }
    528 }
    529 
    530 
    531 /*
    532   returns false in two cases:
    533     - if GetCurDir was used, and GetCurDir returned error.
    534     - if we can't resolve ".." name.
    535   if path is ".", "..", res is empty.
    536   if it's Super Path already, res is empty.
    537   for \**** , and if GetCurDir is not drive (c:\), res is empty
    538   for absolute paths, returns true, res is Super path.
    539 */
    540 
    541 
    542 static bool GetSuperPathBase(CFSTR s, UString &res)
    543 {
    544  res.Empty();
    545  
    546  FChar c = s[0];
    547  if (c == 0)
    548    return true;
    549  if (c == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0)))
    550    return true;
    551  
    552  if (IsSuperOrDevicePath(s))
    553  {
    554    #ifdef LONG_PATH_DOTS_FOLDERS_PARSING
    555    
    556    if ((s)[2] == '.')
    557      return true;
    558 
    559    // we will return true here, so we will try to use these problem paths.
    560 
    561    if (!AreThereDotsFolders(s + kSuperPathPrefixSize))
    562      return true;
    563    
    564    UString temp = fs2us(s);
    565    unsigned fixedSize = GetRootPrefixSize_Of_SuperPath(temp);
    566    if (fixedSize == 0)
    567      return true;
    568 
    569    UString rem = &temp[fixedSize];
    570    if (!ResolveDotsFolders(rem))
    571      return true;
    572 
    573    temp.DeleteFrom(fixedSize);
    574    res += temp;
    575    res += rem;
    576    
    577    #endif
    578 
    579    return true;
    580  }
    581 
    582  if (IS_SEPAR(c))
    583  {
    584    if (IS_SEPAR(s[1]))
    585    {
    586      UString temp = fs2us(s + 2);
    587      unsigned fixedSize = GetRootPrefixSize_Of_NetworkPath(temp);
    588      // we ignore that error to allow short network paths server\share?
    589      /*
    590      if (fixedSize == 0)
    591        return false;
    592      */
    593      UString rem = &temp[fixedSize];
    594      if (!ResolveDotsFolders(rem))
    595        return false;
    596      res += kSuperUncPrefix;
    597      temp.DeleteFrom(fixedSize);
    598      res += temp;
    599      res += rem;
    600      return true;
    601    }
    602  }
    603  else
    604  {
    605    if (IsDrivePath2(s))
    606    {
    607      UString temp = fs2us(s);
    608      unsigned prefixSize = 2;
    609      if (IsDrivePath(s))
    610        prefixSize = kDrivePrefixSize;
    611      UString rem = temp.Ptr(prefixSize);
    612      if (!ResolveDotsFolders(rem))
    613        return true;
    614      res += kSuperPathPrefix;
    615      temp.DeleteFrom(prefixSize);
    616      res += temp;
    617      res += rem;
    618      return true;
    619    }
    620  }
    621 
    622  UString curDir;
    623  if (!GetCurDir(curDir))
    624    return false;
    625  NormalizeDirPathPrefix(curDir);
    626 
    627  unsigned fixedSizeStart = 0;
    628  unsigned fixedSize = 0;
    629  const char *superMarker = NULL;
    630  if (IsSuperPath(curDir))
    631  {
    632    fixedSize = GetRootPrefixSize_Of_SuperPath(curDir);
    633    if (fixedSize == 0)
    634      return false;
    635  }
    636  else
    637  {
    638    if (IsDrivePath(curDir))
    639    {
    640      superMarker = kSuperPathPrefix;
    641      fixedSize = kDrivePrefixSize;
    642    }
    643    else
    644    {
    645      if (!IsPathSepar(curDir[0]) || !IsPathSepar(curDir[1]))
    646        return false;
    647      fixedSizeStart = 2;
    648      fixedSize = GetRootPrefixSize_Of_NetworkPath(curDir.Ptr(2));
    649      if (fixedSize == 0)
    650        return false;
    651      superMarker = kSuperUncPrefix;
    652    }
    653  }
    654  
    655  UString temp;
    656  if (IS_SEPAR(c))
    657  {
    658    temp = fs2us(s + 1);
    659  }
    660  else
    661  {
    662    temp += &curDir[fixedSizeStart + fixedSize];
    663    temp += fs2us(s);
    664  }
    665  if (!ResolveDotsFolders(temp))
    666    return false;
    667  if (superMarker)
    668    res += superMarker;
    669  res += curDir.Mid(fixedSizeStart, fixedSize);
    670  res += temp;
    671  return true;
    672 }
    673 
    674 
    675 /*
    676  In that case if GetSuperPathBase doesn't return new path, we don't need
    677  to use same path that was used as main path
    678                        
    679  GetSuperPathBase  superPath.IsEmpty() onlyIfNew
    680     false            *                *          GetCurDir Error
    681     true            false             *          use Super path
    682     true            true             true        don't use any path, we already used mainPath
    683     true            true             false       use main path as Super Path, we don't try mainMath
    684                                                  That case is possible now if GetCurDir returns unknow
    685                                                  type of path (not drive and not network)
    686 
    687  We can change that code if we want to try mainPath, if GetSuperPathBase returns error,
    688  and we didn't try mainPath still.
    689  If we want to work that way, we don't need to use GetSuperPathBase return code.
    690 */
    691 
    692 bool GetSuperPath(CFSTR path, UString &superPath, bool onlyIfNew)
    693 {
    694  if (GetSuperPathBase(path, superPath))
    695  {
    696    if (superPath.IsEmpty())
    697    {
    698      // actually the only possible when onlyIfNew == true and superPath is empty
    699      // is case when
    700 
    701      if (onlyIfNew)
    702        return false;
    703      superPath = fs2us(path);
    704    }
    705    return true;
    706  }
    707  return false;
    708 }
    709 
    710 bool GetSuperPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2, bool onlyIfNew)
    711 {
    712  if (!GetSuperPathBase(s1, d1) ||
    713      !GetSuperPathBase(s2, d2))
    714    return false;
    715  if (d1.IsEmpty() && d2.IsEmpty() && onlyIfNew)
    716    return false;
    717  if (d1.IsEmpty()) d1 = fs2us(s1);
    718  if (d2.IsEmpty()) d2 = fs2us(s2);
    719  return true;
    720 }
    721 
    722 
    723 /*
    724 // returns true, if we need additional use with New Super path.
    725 bool GetSuperPath(CFSTR path, UString &superPath)
    726 {
    727  if (GetSuperPathBase(path, superPath))
    728    return !superPath.IsEmpty();
    729  return false;
    730 }
    731 */
    732 #endif // WIN_LONG_PATH
    733 
    734 bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res)
    735 {
    736  res = s;
    737 
    738  #ifdef UNDER_CE
    739 
    740  if (!IS_SEPAR(s[0]))
    741  {
    742    if (!dirPrefix)
    743      return false;
    744    res = dirPrefix;
    745    res += s;
    746  }
    747 
    748  #else
    749 
    750  unsigned prefixSize = GetRootPrefixSize(s);
    751  if (prefixSize != 0)
    752  {
    753    if (!AreThereDotsFolders(s + prefixSize))
    754      return true;
    755    
    756    UString rem = fs2us(s + prefixSize);
    757    if (!ResolveDotsFolders(rem))
    758      return true; // maybe false;
    759    res.DeleteFrom(prefixSize);
    760    res += us2fs(rem);
    761    return true;
    762  }
    763 
    764  /*
    765  FChar c = s[0];
    766  if (c == 0)
    767    return true;
    768  if (c == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0)))
    769    return true;
    770  if (IS_SEPAR(c) && IS_SEPAR(s[1]))
    771    return true;
    772  if (IsDrivePath(s))
    773    return true;
    774  */
    775 
    776  UString curDir;
    777  if (dirPrefix)
    778    curDir = fs2us(dirPrefix);
    779  else
    780  {
    781    if (!GetCurDir(curDir))
    782      return false;
    783  }
    784  NormalizeDirPathPrefix(curDir);
    785 
    786  unsigned fixedSize = 0;
    787 
    788  #ifdef _WIN32
    789 
    790  if (IsSuperPath(curDir))
    791  {
    792    fixedSize = GetRootPrefixSize_Of_SuperPath(curDir);
    793    if (fixedSize == 0)
    794      return false;
    795  }
    796  else
    797  {
    798    if (IsDrivePath(curDir))
    799      fixedSize = kDrivePrefixSize;
    800    else
    801    {
    802      if (!IsPathSepar(curDir[0]) || !IsPathSepar(curDir[1]))
    803        return false;
    804      fixedSize = GetRootPrefixSize_Of_NetworkPath(curDir.Ptr(2));
    805      if (fixedSize == 0)
    806        return false;
    807      fixedSize += 2;
    808    }
    809  }
    810 
    811  #endif // _WIN32
    812  
    813  UString temp;
    814  if (IS_SEPAR(s[0]))
    815  {
    816    temp = fs2us(s + 1);
    817  }
    818  else
    819  {
    820    temp += curDir.Ptr(fixedSize);
    821    temp += fs2us(s);
    822  }
    823  if (!ResolveDotsFolders(temp))
    824    return false;
    825  curDir.DeleteFrom(fixedSize);
    826  res = us2fs(curDir);
    827  res += us2fs(temp);
    828  
    829  #endif // UNDER_CE
    830 
    831  return true;
    832 }
    833 
    834 bool GetFullPath(CFSTR path, FString &fullPath)
    835 {
    836  return GetFullPath(NULL, path, fullPath);
    837 }
    838 
    839 }}}