misc/libphysfs/lzma/CPP/Windows/FileDir.cpp
changeset 12213 bb5522e88ab2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/CPP/Windows/FileDir.cpp	Mon Apr 10 12:06:43 2017 -0400
@@ -0,0 +1,841 @@
+// Windows/FileDir.cpp
+
+#include "StdAfx.h"
+
+#include "FileDir.h"
+#include "FileName.h"
+#include "FileFind.h"
+#include "Defs.h"
+#ifndef _UNICODE
+#include "../Common/StringConvert.h"
+#endif
+
+#ifndef _UNICODE
+extern bool g_IsNT;
+#endif
+
+namespace NWindows {
+namespace NFile {
+
+#if defined(WIN_LONG_PATH) && defined(_UNICODE)
+#define WIN_LONG_PATH2
+#endif
+
+// SetCurrentDirectory doesn't support \\?\ prefix
+
+#ifdef WIN_LONG_PATH
+bool GetLongPathBase(LPCWSTR fileName, UString &res);
+bool GetLongPath(LPCWSTR fileName, UString &res);
+#endif
+
+namespace NDirectory {
+
+#ifndef _UNICODE
+static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } 
+static UString GetUnicodePath(const CSysString &sysPath)
+  { return MultiByteToUnicodeString(sysPath, GetCurrentCodePage()); }
+static CSysString GetSysPath(LPCWSTR sysPath)
+  { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); }
+#endif
+
+bool MyGetWindowsDirectory(CSysString &path)
+{
+  UINT needLength = ::GetWindowsDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);
+  path.ReleaseBuffer();
+  return (needLength > 0 && needLength <= MAX_PATH);
+}
+
+bool MyGetSystemDirectory(CSysString &path)
+{
+  UINT needLength = ::GetSystemDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);
+  path.ReleaseBuffer();
+  return (needLength > 0 && needLength <= MAX_PATH);
+}
+
+#ifndef _UNICODE
+bool MyGetWindowsDirectory(UString &path)
+{
+  if (g_IsNT)
+  {
+    UINT needLength = ::GetWindowsDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);
+    path.ReleaseBuffer();
+    return (needLength > 0 && needLength <= MAX_PATH);
+  }
+  CSysString sysPath;
+  if (!MyGetWindowsDirectory(sysPath))
+    return false;
+  path = GetUnicodePath(sysPath);
+  return true;
+}
+
+bool MyGetSystemDirectory(UString &path)
+{
+  if (g_IsNT)
+  {
+    UINT needLength = ::GetSystemDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);
+    path.ReleaseBuffer();
+    return (needLength > 0 && needLength <= MAX_PATH);
+  }
+  CSysString sysPath;
+  if (!MyGetSystemDirectory(sysPath))
+    return false;
+  path = GetUnicodePath(sysPath);
+  return true;
+}
+#endif
+
+bool SetDirTime(LPCWSTR fileName, const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime)
+{
+  #ifndef _UNICODE
+  if (!g_IsNT)
+  {
+    ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return false;
+  }
+  #endif 
+  HANDLE hDir = ::CreateFileW(fileName, GENERIC_WRITE,
+      FILE_SHARE_READ | FILE_SHARE_WRITE,
+      NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+  #ifdef WIN_LONG_PATH
+  if (hDir == INVALID_HANDLE_VALUE)
+  {
+    UString longPath;
+    if (GetLongPath(fileName, longPath))
+      hDir = ::CreateFileW(longPath, GENERIC_WRITE,
+        FILE_SHARE_READ | FILE_SHARE_WRITE,
+        NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+  }
+  #endif
+
+  bool res = false;
+  if (hDir != INVALID_HANDLE_VALUE)
+  {
+    res = BOOLToBool(::SetFileTime(hDir, creationTime, lastAccessTime, lastWriteTime));
+    ::CloseHandle(hDir);
+  }
+  return res;
+}
+
+bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes)
+{
+  if (::SetFileAttributes(fileName, fileAttributes))
+    return true;
+  #ifdef WIN_LONG_PATH2
+  UString longPath;
+  if (GetLongPath(fileName, longPath))
+    return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes));
+  #endif
+  return false;
+}
+
+bool MyRemoveDirectory(LPCTSTR pathName)
+{ 
+  if (::RemoveDirectory(pathName))
+    return true;
+  #ifdef WIN_LONG_PATH2
+  UString longPath;
+  if (GetLongPath(pathName, longPath))
+    return BOOLToBool(::RemoveDirectoryW(longPath));
+  #endif
+  return false;
+}
+
+#ifdef WIN_LONG_PATH
+bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2)
+{
+  if (!GetLongPathBase(s1, d1) || !GetLongPathBase(s2, d2))
+    return false;
+  if (d1.IsEmpty() && d2.IsEmpty()) return false;
+  if (d1.IsEmpty()) d1 = s1;
+  if (d2.IsEmpty()) d2 = s2;
+  return true;
+}
+#endif
+
+bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName)
+{ 
+  if (::MoveFile(existFileName, newFileName))
+    return true;
+  #ifdef WIN_LONG_PATH2
+  UString d1, d2;
+  if (GetLongPaths(existFileName, newFileName, d1, d2)) 
+    return BOOLToBool(::MoveFileW(d1, d2));
+  #endif
+  return false;
+}
+
+#ifndef _UNICODE
+bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes)
+{  
+  if (!g_IsNT)
+    return MySetFileAttributes(GetSysPath(fileName), fileAttributes);
+  if (::SetFileAttributesW(fileName, fileAttributes))
+    return true;
+  #ifdef WIN_LONG_PATH
+  UString longPath;
+  if (GetLongPath(fileName, longPath))
+    return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes));
+  #endif
+  return false;
+}
+
+
+bool MyRemoveDirectory(LPCWSTR pathName)
+{  
+  if (!g_IsNT)
+    return MyRemoveDirectory(GetSysPath(pathName));
+  if (::RemoveDirectoryW(pathName))
+    return true;
+  #ifdef WIN_LONG_PATH
+  UString longPath;
+  if (GetLongPath(pathName, longPath))
+    return BOOLToBool(::RemoveDirectoryW(longPath));
+  #endif
+  return false;
+}
+
+bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName)
+{  
+  if (!g_IsNT)
+    return MyMoveFile(GetSysPath(existFileName), GetSysPath(newFileName));
+  if (::MoveFileW(existFileName, newFileName))
+    return true;
+  #ifdef WIN_LONG_PATH
+  UString d1, d2;
+  if (GetLongPaths(existFileName, newFileName, d1, d2)) 
+    return BOOLToBool(::MoveFileW(d1, d2));
+  #endif
+  return false;
+}
+#endif
+
+bool MyCreateDirectory(LPCTSTR pathName) 
+{ 
+  if (::CreateDirectory(pathName, NULL))
+    return true;
+  #ifdef WIN_LONG_PATH2
+  if (::GetLastError() != ERROR_ALREADY_EXISTS)
+  {
+    UString longPath;
+    if (GetLongPath(pathName, longPath))
+      return BOOLToBool(::CreateDirectoryW(longPath, NULL));
+  }
+  #endif
+  return false;
+}
+
+#ifndef _UNICODE
+bool MyCreateDirectory(LPCWSTR pathName)
+{  
+  if (!g_IsNT)
+    return MyCreateDirectory(GetSysPath(pathName));
+  if (::CreateDirectoryW(pathName, NULL))
+    return true;
+  #ifdef WIN_LONG_PATH
+  if (::GetLastError() != ERROR_ALREADY_EXISTS)
+  {
+    UString longPath;
+    if (GetLongPath(pathName, longPath))
+      return BOOLToBool(::CreateDirectoryW(longPath, NULL));
+  }
+  #endif
+  return false;
+}
+#endif
+
+/*
+bool CreateComplexDirectory(LPCTSTR pathName)
+{
+  NName::CParsedPath path;
+  path.ParsePath(pathName);
+  CSysString fullPath = path.Prefix;
+  DWORD errorCode = ERROR_SUCCESS;
+  for(int i = 0; i < path.PathParts.Size(); i++)
+  {
+    const CSysString &string = path.PathParts[i];
+    if(string.IsEmpty())
+    {
+      if(i != path.PathParts.Size() - 1)
+        return false;
+      return true;
+    }
+    fullPath += path.PathParts[i];
+    if (!MyCreateDirectory(fullPath))
+    {
+      DWORD errorCode = GetLastError();
+      if(errorCode != ERROR_ALREADY_EXISTS)
+        return false;
+    }
+    fullPath += NName::kDirDelimiter;
+  }
+  return true;
+}
+*/
+
+bool CreateComplexDirectory(LPCTSTR _aPathName)
+{
+  CSysString pathName = _aPathName;
+  int pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR));
+  if (pos > 0 && pos == pathName.Length() - 1)
+  {
+    if (pathName.Length() == 3 && pathName[1] == ':')
+      return true; // Disk folder;
+    pathName.Delete(pos);
+  }
+  CSysString pathName2 = pathName;
+  pos = pathName.Length();
+  for (;;)
+  {
+    if(MyCreateDirectory(pathName))
+      break;
+    if (::GetLastError() == ERROR_ALREADY_EXISTS)
+    {
+      NFind::CFileInfo fileInfo;
+      if (!NFind::FindFile(pathName, fileInfo)) // For network folders
+        return true;
+      if (!fileInfo.IsDirectory())
+        return false;
+      break;
+    }
+    pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR));
+    if (pos < 0 || pos == 0)
+      return false;
+    if (pathName[pos - 1] == ':')
+      return false;
+    pathName = pathName.Left(pos);
+  }
+  pathName = pathName2;
+  while(pos < pathName.Length())
+  {
+    pos = pathName.Find(TEXT(CHAR_PATH_SEPARATOR), pos + 1);
+    if (pos < 0)
+      pos = pathName.Length();
+    if (!MyCreateDirectory(pathName.Left(pos)))
+      return false;
+  }
+  return true;
+}
+
+#ifndef _UNICODE
+
+bool CreateComplexDirectory(LPCWSTR _aPathName)
+{
+  UString pathName = _aPathName;
+  int pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR);
+  if (pos > 0 && pos == pathName.Length() - 1)
+  {
+    if (pathName.Length() == 3 && pathName[1] == L':')
+      return true; // Disk folder;
+    pathName.Delete(pos);
+  }
+  UString pathName2 = pathName;
+  pos = pathName.Length();
+  for (;;)
+  {
+    if(MyCreateDirectory(pathName))
+      break;
+    if (::GetLastError() == ERROR_ALREADY_EXISTS)
+    {
+      NFind::CFileInfoW fileInfo;
+      if (!NFind::FindFile(pathName, fileInfo)) // For network folders
+        return true;
+      if (!fileInfo.IsDirectory())
+        return false;
+      break;
+    }
+    pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR);
+    if (pos < 0 || pos == 0)
+      return false;
+    if (pathName[pos - 1] == L':')
+      return false;
+    pathName = pathName.Left(pos);
+  }
+  pathName = pathName2;
+  while(pos < pathName.Length())
+  {
+    pos = pathName.Find(WCHAR_PATH_SEPARATOR, pos + 1);
+    if (pos < 0)
+      pos = pathName.Length();
+    if (!MyCreateDirectory(pathName.Left(pos)))
+      return false;
+  }
+  return true;
+}
+
+#endif
+
+bool DeleteFileAlways(LPCTSTR name)
+{
+  if (!MySetFileAttributes(name, 0))
+    return false;
+  if (::DeleteFile(name))
+    return true;
+  #ifdef WIN_LONG_PATH2
+  UString longPath;
+  if (GetLongPath(name, longPath))
+    return BOOLToBool(::DeleteFileW(longPath));
+  #endif
+  return false;
+}
+
+#ifndef _UNICODE
+bool DeleteFileAlways(LPCWSTR name)
+{  
+  if (!g_IsNT)
+    return DeleteFileAlways(GetSysPath(name));
+  if (!MySetFileAttributes(name, 0))
+    return false;
+  if (::DeleteFileW(name))
+    return true;
+  #ifdef WIN_LONG_PATH
+  UString longPath;
+  if (GetLongPath(name, longPath))
+    return BOOLToBool(::DeleteFileW(longPath));
+  #endif
+  return false;
+}
+#endif
+
+static bool RemoveDirectorySubItems2(const CSysString pathPrefix, const NFind::CFileInfo &fileInfo)
+{
+  if(fileInfo.IsDirectory())
+    return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name);
+  return DeleteFileAlways(pathPrefix + fileInfo.Name);
+}
+
+bool RemoveDirectoryWithSubItems(const CSysString &path)
+{
+  NFind::CFileInfo fileInfo;
+  CSysString pathPrefix = path + NName::kDirDelimiter;
+  {
+    NFind::CEnumerator enumerator(pathPrefix + TCHAR(NName::kAnyStringWildcard));
+    while(enumerator.Next(fileInfo))
+      if (!RemoveDirectorySubItems2(pathPrefix, fileInfo))
+        return false;
+  }
+  if (!MySetFileAttributes(path, 0))
+    return false;
+  return MyRemoveDirectory(path);
+}
+
+#ifndef _UNICODE
+static bool RemoveDirectorySubItems2(const UString pathPrefix, const NFind::CFileInfoW &fileInfo)
+{
+  if(fileInfo.IsDirectory())
+    return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name);
+  return DeleteFileAlways(pathPrefix + fileInfo.Name);
+}
+bool RemoveDirectoryWithSubItems(const UString &path)
+{
+  NFind::CFileInfoW fileInfo;
+  UString pathPrefix = path + UString(NName::kDirDelimiter);
+  {
+    NFind::CEnumeratorW enumerator(pathPrefix + UString(NName::kAnyStringWildcard));
+    while(enumerator.Next(fileInfo))
+      if (!RemoveDirectorySubItems2(pathPrefix, fileInfo))
+        return false;
+  }
+  if (!MySetFileAttributes(path, 0))
+    return false;
+  return MyRemoveDirectory(path);
+}
+#endif
+
+#ifndef _WIN32_WCE
+
+bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath)
+{
+  DWORD needLength = ::GetShortPathName(longPath, shortPath.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);
+  shortPath.ReleaseBuffer();
+  return (needLength > 0 && needLength < MAX_PATH);
+}
+
+bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex)
+{
+  resultPath.Empty();
+  LPTSTR fileNamePointer = 0;
+  LPTSTR buffer = resultPath.GetBuffer(MAX_PATH);
+  DWORD needLength = ::GetFullPathName(fileName, MAX_PATH + 1, buffer, &fileNamePointer);
+  resultPath.ReleaseBuffer();
+  if (needLength == 0)
+    return false;
+  if (needLength >= MAX_PATH)
+  {
+    #ifdef WIN_LONG_PATH2
+    needLength++;
+    buffer = resultPath.GetBuffer(needLength + 1);
+    DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer);
+    resultPath.ReleaseBuffer();
+    if (needLength2 == 0 || needLength2 > needLength)
+    #endif
+      return false;
+  }
+  if (fileNamePointer == 0)
+    fileNamePartStartIndex = lstrlen(fileName);
+  else
+    fileNamePartStartIndex = (int)(fileNamePointer - buffer);
+  return true;
+}
+
+#ifndef _UNICODE
+bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex)
+{
+  resultPath.Empty();
+  if (g_IsNT)
+  {
+    LPWSTR fileNamePointer = 0;
+    LPWSTR buffer = resultPath.GetBuffer(MAX_PATH);
+    DWORD needLength = ::GetFullPathNameW(fileName, MAX_PATH + 1, buffer, &fileNamePointer);
+    resultPath.ReleaseBuffer();
+    if (needLength == 0)
+      return false;
+    if (needLength >= MAX_PATH)
+    {
+      #ifdef WIN_LONG_PATH
+      needLength++;
+      buffer = resultPath.GetBuffer(needLength + 1);
+      DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer);
+      resultPath.ReleaseBuffer();
+      if (needLength2 == 0 || needLength2 > needLength)
+      #endif
+        return false;
+    }
+    if (fileNamePointer == 0)
+      fileNamePartStartIndex = MyStringLen(fileName);
+    else
+      fileNamePartStartIndex = (int)(fileNamePointer - buffer);
+  }
+  else
+  {
+    CSysString sysPath;
+    if (!MyGetFullPathName(GetSysPath(fileName), sysPath, fileNamePartStartIndex))
+      return false;
+    UString resultPath1 = GetUnicodePath(sysPath.Left(fileNamePartStartIndex));
+    UString resultPath2 = GetUnicodePath(sysPath.Mid(fileNamePartStartIndex));
+    fileNamePartStartIndex = resultPath1.Length();
+    resultPath = resultPath1 + resultPath2;
+  }
+  return true;
+}
+#endif
+
+
+bool MyGetFullPathName(LPCTSTR fileName, CSysString &path)
+{
+  int index;
+  return MyGetFullPathName(fileName, path, index);
+}
+
+#ifndef _UNICODE
+bool MyGetFullPathName(LPCWSTR fileName, UString &path)
+{
+  int index;
+  return MyGetFullPathName(fileName, path, index);
+}
+#endif
+
+bool GetOnlyName(LPCTSTR fileName, CSysString &resultName)
+{
+  int index;
+  if (!MyGetFullPathName(fileName, resultName, index))
+    return false;
+  resultName = resultName.Mid(index);
+  return true;
+}
+
+#ifndef _UNICODE
+bool GetOnlyName(LPCWSTR fileName, UString &resultName)
+{
+  int index;
+  if (!MyGetFullPathName(fileName, resultName, index))
+    return false;
+  resultName = resultName.Mid(index);
+  return true;
+}
+#endif
+
+bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName)
+{
+  int index;
+  if (!MyGetFullPathName(fileName, resultName, index))
+    return false;
+  resultName = resultName.Left(index);
+  return true;
+}
+
+#ifndef _UNICODE
+bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName)
+{
+  int index;
+  if (!MyGetFullPathName(fileName, resultName, index))
+    return false;
+  resultName = resultName.Left(index);
+  return true;
+}
+#endif
+
+bool MyGetCurrentDirectory(CSysString &path)
+{
+  DWORD needLength = ::GetCurrentDirectory(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1));
+  path.ReleaseBuffer();
+  return (needLength > 0 && needLength <= MAX_PATH);
+}
+
+#ifndef _UNICODE
+bool MySetCurrentDirectory(LPCWSTR path)
+{
+  if (g_IsNT)
+    return BOOLToBool(::SetCurrentDirectoryW(path));
+  return MySetCurrentDirectory(GetSysPath(path));
+}
+bool MyGetCurrentDirectory(UString &path)
+{
+  if (g_IsNT)
+  {
+    DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1));
+    path.ReleaseBuffer();
+    return (needLength > 0 && needLength <= MAX_PATH);
+  }
+  CSysString sysPath;
+  if (!MyGetCurrentDirectory(sysPath))
+    return false;
+  path = GetUnicodePath(sysPath);
+  return true;
+}
+#endif
+#endif
+
+bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, 
+  CSysString &resultPath, UINT32 &filePart)
+{
+  LPTSTR filePartPointer;
+  DWORD value = ::SearchPath(path, fileName, extension, 
+    MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer);
+  filePart = (UINT32)(filePartPointer - (LPCTSTR)resultPath);
+  resultPath.ReleaseBuffer();
+  return (value > 0 && value <= MAX_PATH);
+}
+
+#ifndef _UNICODE
+bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, 
+  UString &resultPath, UINT32 &filePart)
+{
+  if (g_IsNT)
+  {
+    LPWSTR filePartPointer = 0;
+    DWORD value = ::SearchPathW(path, fileName, extension, 
+        MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer);
+    filePart = (UINT32)(filePartPointer - (LPCWSTR)resultPath);
+    resultPath.ReleaseBuffer();
+    return (value > 0 && value <= MAX_PATH);
+  }
+  
+  CSysString sysPath;
+  if (!MySearchPath(
+      path != 0 ? (LPCTSTR)GetSysPath(path): 0,
+      fileName != 0 ? (LPCTSTR)GetSysPath(fileName): 0,
+      extension != 0 ? (LPCTSTR)GetSysPath(extension): 0,
+      sysPath, filePart))
+    return false;
+  UString resultPath1 = GetUnicodePath(sysPath.Left(filePart));
+  UString resultPath2 = GetUnicodePath(sysPath.Mid(filePart));
+  filePart = resultPath1.Length();
+  resultPath = resultPath1 + resultPath2;
+  return true;
+}
+#endif
+
+bool MyGetTempPath(CSysString &path)
+{
+  DWORD needLength = ::GetTempPath(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1));
+  path.ReleaseBuffer();
+  return (needLength > 0 && needLength <= MAX_PATH);
+}
+
+#ifndef _UNICODE
+bool MyGetTempPath(UString &path)
+{
+  path.Empty();
+  if (g_IsNT)
+  {
+    DWORD needLength = ::GetTempPathW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1));
+    path.ReleaseBuffer();
+    return (needLength > 0 && needLength <= MAX_PATH);
+  }
+  CSysString sysPath;
+  if (!MyGetTempPath(sysPath))
+    return false;
+  path = GetUnicodePath(sysPath);
+  return true;
+}
+#endif
+
+UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &path)
+{
+  UINT number = ::GetTempFileName(dirPath, prefix, 0, path.GetBuffer(MAX_PATH + 1));
+  path.ReleaseBuffer();
+  return number;
+}
+
+#ifndef _UNICODE
+UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &path)
+{
+  if (g_IsNT)
+  {
+    UINT number = ::GetTempFileNameW(dirPath, prefix, 0, path.GetBuffer(MAX_PATH));
+    path.ReleaseBuffer();
+    return number;
+  }
+  CSysString sysPath;
+  UINT number = MyGetTempFileName(
+      dirPath ? (LPCTSTR)GetSysPath(dirPath): 0, 
+      prefix ? (LPCTSTR)GetSysPath(prefix): 0, 
+      sysPath);
+  path = GetUnicodePath(sysPath);
+  return number;
+}
+#endif
+
+UINT CTempFile::Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath)
+{
+  Remove();
+  UINT number = MyGetTempFileName(dirPath, prefix, resultPath);
+  if(number != 0)
+  {
+    _fileName = resultPath;
+    _mustBeDeleted = true;
+  }
+  return number;
+}
+
+bool CTempFile::Create(LPCTSTR prefix, CSysString &resultPath)
+{
+  CSysString tempPath;
+  if (!MyGetTempPath(tempPath))
+    return false;
+  if (Create(tempPath, prefix, resultPath) != 0)
+    return true;
+  if (!MyGetWindowsDirectory(tempPath))
+    return false;
+  return (Create(tempPath, prefix, resultPath) != 0);
+}
+
+bool CTempFile::Remove()
+{
+  if (!_mustBeDeleted)
+    return true;
+  _mustBeDeleted = !DeleteFileAlways(_fileName);
+  return !_mustBeDeleted;
+}
+
+#ifndef _UNICODE
+
+UINT CTempFileW::Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath)
+{
+  Remove();
+  UINT number = MyGetTempFileName(dirPath, prefix, resultPath);
+  if(number != 0)
+  {
+    _fileName = resultPath;
+    _mustBeDeleted = true;
+  }
+  return number;
+}
+
+bool CTempFileW::Create(LPCWSTR prefix, UString &resultPath)
+{
+  UString tempPath;
+  if (!MyGetTempPath(tempPath))
+    return false;
+  if (Create(tempPath, prefix, resultPath) != 0)
+    return true;
+  if (!MyGetWindowsDirectory(tempPath))
+    return false;
+  return (Create(tempPath, prefix, resultPath) != 0);
+}
+
+bool CTempFileW::Remove()
+{
+  if (!_mustBeDeleted)
+    return true;
+  _mustBeDeleted = !DeleteFileAlways(_fileName);
+  return !_mustBeDeleted;
+}
+
+#endif
+
+bool CreateTempDirectory(LPCTSTR prefix, CSysString &dirName)
+{
+  /*
+  CSysString prefix = tempPath + prefixChars;
+  CRandom random;
+  random.Init();
+  */
+  for (;;)
+  {
+    CTempFile tempFile;
+    if (!tempFile.Create(prefix, dirName))
+      return false;
+    if (!::DeleteFile(dirName))
+      return false;
+    /*
+    UINT32 randomNumber = random.Generate();
+    TCHAR randomNumberString[32];
+    _stprintf(randomNumberString, _T("%04X"), randomNumber);
+    dirName = prefix + randomNumberString;
+    */
+    if(NFind::DoesFileExist(dirName))
+      continue;
+    if (MyCreateDirectory(dirName))
+      return true;
+    if (::GetLastError() != ERROR_ALREADY_EXISTS)
+      return false;
+  }
+}
+
+bool CTempDirectory::Create(LPCTSTR prefix)
+{ 
+  Remove();
+  return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir)); 
+}
+
+#ifndef _UNICODE
+
+bool CreateTempDirectory(LPCWSTR prefix, UString &dirName)
+{
+  /*
+  CSysString prefix = tempPath + prefixChars;
+  CRandom random;
+  random.Init();
+  */
+  for (;;)
+  {
+    CTempFileW tempFile;
+    if (!tempFile.Create(prefix, dirName))
+      return false;
+    if (!DeleteFileAlways(dirName))
+      return false;
+    /*
+    UINT32 randomNumber = random.Generate();
+    TCHAR randomNumberString[32];
+    _stprintf(randomNumberString, _T("%04X"), randomNumber);
+    dirName = prefix + randomNumberString;
+    */
+    if(NFind::DoesFileExist(dirName))
+      continue;
+    if (MyCreateDirectory(dirName))
+      return true;
+    if (::GetLastError() != ERROR_ALREADY_EXISTS)
+      return false;
+  }
+}
+
+bool CTempDirectoryW::Create(LPCWSTR prefix)
+{ 
+  Remove();
+  return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir)); 
+}
+
+#endif
+
+}}}