/* WinXP-64 CreateDir(): "" - ERROR_PATH_NOT_FOUND \ - ERROR_ACCESS_DENIED C:\ - ERROR_ACCESS_DENIED, if there is such drive, D:\folder - ERROR_PATH_NOT_FOUND, if there is no such drive, C:\nonExistent\folder - ERROR_PATH_NOT_FOUND C:\existFolder - ERROR_ALREADY_EXISTS C:\existFolder\ - ERROR_ALREADY_EXISTS
bool CreateDir(CFSTR path)
{ #ifndef _UNICODE if (!g_IsNT)
{ if (::CreateDirectory(fs2fas(path), NULL)) returntrue;
} else #endif
{
IF_USE_MAIN_PATH if (::CreateDirectoryW(fs2us(path), NULL)) returntrue; #ifdef WIN_LONG_PATH if ((!USE_MAIN_PATH || ::GetLastError() != ERROR_ALREADY_EXISTS) && USE_SUPER_PATH)
{
UString superPath; if (GetSuperPath(path, superPath, USE_MAIN_PATH)) return BOOLToBool(::CreateDirectoryW(superPath, NULL));
} #endif
} returnfalse;
}
/* CreateDir2 returns true, if directory can contain files after the call (two cases): 1) the directory already exists 2) the directory was created path must be WITHOUT trailing path separator.
We need CreateDir2, since fileInfo.Find() for reserved names like "com8"
returns FILE instead of DIRECTORY. And we need to use SuperPath */
staticbool CreateDir2(CFSTR path)
{ #ifndef _UNICODE if (!g_IsNT)
{ if (::CreateDirectory(fs2fas(path), NULL)) returntrue;
} else #endif
{
IF_USE_MAIN_PATH if (::CreateDirectoryW(fs2us(path), NULL)) returntrue; #ifdef WIN_LONG_PATH if ((!USE_MAIN_PATH || ::GetLastError() != ERROR_ALREADY_EXISTS) && USE_SUPER_PATH)
{
UString superPath; if (GetSuperPath(path, superPath, USE_MAIN_PATH))
{ if (::CreateDirectoryW(superPath, NULL)) returntrue; if (::GetLastError() != ERROR_ALREADY_EXISTS) returnfalse;
NFind::CFileInfo fi; if (!fi.Find(us2fs(superPath))) returnfalse; return fi.IsDir();
}
} #endif
} if (::GetLastError() != ERROR_ALREADY_EXISTS) returnfalse;
NFind::CFileInfo fi; if (!fi.Find(path)) returnfalse; return fi.IsDir();
}
if (IsDriveRootPath_SuperAllowed(_path)) returnfalse;
unsigned prefixSize = GetRootPrefixSize(_path);
#endif
#endif
FString path (_path);
int pos = path.ReverseFind_PathSepar(); if (pos >= 0 && (unsigned)pos == path.Len() - 1)
{ if (path.Len() == 1) returntrue;
path.DeleteBack();
}
const FString path2 (path);
pos = path.Len();
for (;;)
{ if (CreateDir2(path)) break; if (::GetLastError() == ERROR_ALREADY_EXISTS) returnfalse;
pos = path.ReverseFind_PathSepar(); if (pos < 0 || pos == 0) returnfalse;
#ifdefined(_WIN32) && !defined(UNDER_CE) if (pos == 1 && IS_PATH_SEPAR(path[0])) returnfalse; if (prefixSize >= (unsigned)pos + 1) returnfalse; #endif
path.DeleteFrom(pos);
}
while (pos < (int)path2.Len())
{ int pos2 = NName::FindSepar(path2.Ptr(pos + 1)); if (pos2 < 0)
pos = path2.Len(); else
pos += 1 + pos2;
path.SetFrom(path2, pos); if (!CreateDir(path)) returnfalse;
}
returntrue;
}
bool DeleteFileAlways(CFSTR path)
{ /* If alt stream, we also need to clear READ-ONLY attribute of main file before delete.
SetFileAttrib("name:stream", ) changes attributes of main file. */
{
DWORD attrib = NFind::GetFileAttrib(path); if (attrib != INVALID_FILE_ATTRIBUTES
&& (attrib & FILE_ATTRIBUTE_DIRECTORY) == 0
&& (attrib & FILE_ATTRIBUTE_READONLY) != 0)
{ if (!SetFileAttrib(path, attrib & ~FILE_ATTRIBUTE_READONLY)) returnfalse;
}
}
#ifndef _UNICODE if (!g_IsNT)
{ if (::DeleteFile(fs2fas(path))) returntrue;
} else #endif
{ /* DeleteFile("name::$DATA") deletes all alt streams (same as delete DeleteFile("name")).
Maybe it's better to open "name::$DATA" and clear data for unnamed stream? */
IF_USE_MAIN_PATH if (::DeleteFileW(fs2us(path))) returntrue; #ifdef WIN_LONG_PATH if (USE_SUPER_PATH)
{
UString superPath; if (GetSuperPath(path, superPath, USE_MAIN_PATH)) return BOOLToBool(::DeleteFileW(superPath));
} #endif
} returnfalse;
}
bool RemoveDirWithSubItems(const FString &path)
{ bool needRemoveSubItems = true;
{
NFind::CFileInfo fi; if (!fi.Find(path)) returnfalse; if (!fi.IsDir())
{
::SetLastError(ERROR_DIRECTORY); returnfalse;
} if (fi.HasReparsePoint())
needRemoveSubItems = false;
}
if (needRemoveSubItems)
{
FString s (path);
s.Add_PathSepar(); constunsigned prefixSize = s.Len();
NFind::CEnumerator enumerator;
enumerator.SetDirPrefix(s);
NFind::CFileInfo fi; while (enumerator.Next(fi))
{
s.DeleteFrom(prefixSize);
s += fi.Name; if (fi.IsDir())
{ if (!RemoveDirWithSubItems(s)) returnfalse;
} elseif (!DeleteFileAlways(s)) returnfalse;
}
}
if (!SetFileAttrib(path, 0)) returnfalse; return RemoveDir(path);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.