mirror of
https://github.com/Xevion/easy7zip.git
synced 2026-01-31 02:24:11 -06:00
15.05
This commit is contained in:
committed by
Kornel Lesiński
parent
0713a3ab80
commit
54490d51d5
+5
-5
@@ -14,11 +14,11 @@ namespace NCOM {
|
||||
|
||||
UString GUIDToStringW(REFGUID guid)
|
||||
{
|
||||
UString string;
|
||||
const int kStringSize = 48;
|
||||
StringFromGUID2(guid, string.GetBuffer(kStringSize), kStringSize);
|
||||
string.ReleaseBuffer();
|
||||
return string;
|
||||
UString s;
|
||||
const unsigned kSize = 48;
|
||||
StringFromGUID2(guid, s.GetBuf(kSize), kSize);
|
||||
s.ReleaseBuf_CalcLen(kSize);
|
||||
return s;
|
||||
}
|
||||
|
||||
AString GUIDToStringA(REFGUID guid)
|
||||
|
||||
+3
-1
@@ -22,7 +22,7 @@ public:
|
||||
CoInitialize(NULL);
|
||||
#endif
|
||||
};
|
||||
~CComInitializer() { CoUninitialize(); };
|
||||
~CComInitializer() { CoUninitialize(); }
|
||||
};
|
||||
|
||||
class CStgMedium
|
||||
@@ -45,6 +45,7 @@ public:
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
//////////////////////////////////
|
||||
// GUID <--> String Conversions
|
||||
UString GUIDToStringW(REFGUID guid);
|
||||
@@ -62,6 +63,7 @@ HRESULT StringToGUIDA(const char *string, GUID &classID);
|
||||
#else
|
||||
#define StringToGUID StringToGUIDA
|
||||
#endif
|
||||
*/
|
||||
|
||||
}}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ class CBase
|
||||
protected:
|
||||
HANDLE m_Object;
|
||||
public:
|
||||
void Attach(HANDLE handle) { m_Object = handle; };
|
||||
void Attach(HANDLE handle) { m_Object = handle; }
|
||||
bool GetMode(DWORD &mode)
|
||||
{ return BOOLToBool(::GetConsoleMode(m_Object, &mode)); }
|
||||
bool SetMode(DWORD mode)
|
||||
|
||||
@@ -18,11 +18,15 @@ namespace NControl {
|
||||
LRESULT CComboBox::GetLBText(int index, CSysString &s)
|
||||
{
|
||||
s.Empty();
|
||||
LRESULT len = GetLBTextLen(index);
|
||||
LRESULT len = GetLBTextLen(index); // length, excluding the terminating null character
|
||||
if (len == CB_ERR)
|
||||
return len;
|
||||
len = GetLBText(index, s.GetBuffer((int)len + 1));
|
||||
s.ReleaseBuffer();
|
||||
LRESULT len2 = GetLBText(index, s.GetBuf((unsigned)len));
|
||||
if (len2 == CB_ERR)
|
||||
return len;
|
||||
if (len > len2)
|
||||
len = len2;
|
||||
s.ReleaseBuf_CalcLen((unsigned)len);
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -42,8 +46,12 @@ LRESULT CComboBox::GetLBText(int index, UString &s)
|
||||
LRESULT len = SendMessageW(CB_GETLBTEXTLEN, index, 0);
|
||||
if (len == CB_ERR)
|
||||
return len;
|
||||
len = SendMessageW(CB_GETLBTEXT, index, (LPARAM)s.GetBuffer((int)len + 1));
|
||||
s.ReleaseBuffer();
|
||||
LRESULT len2 = SendMessageW(CB_GETLBTEXT, index, (LPARAM)s.GetBuf((unsigned)len));
|
||||
if (len2 == CB_ERR)
|
||||
return len;
|
||||
if (len > len2)
|
||||
len = len2;
|
||||
s.ReleaseBuf_CalcLen(len);
|
||||
return len;
|
||||
}
|
||||
AString sa;
|
||||
|
||||
@@ -95,9 +95,9 @@ public:
|
||||
|
||||
/*
|
||||
#ifdef UNDER_CE
|
||||
virtual void OnHelp(void *) { OnHelp(); };
|
||||
virtual void OnHelp(void *) { OnHelp(); }
|
||||
#else
|
||||
virtual void OnHelp(LPHELPINFO) { OnHelp(); };
|
||||
virtual void OnHelp(LPHELPINFO) { OnHelp(); }
|
||||
#endif
|
||||
*/
|
||||
virtual void OnHelp() {};
|
||||
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
virtual void OnDestroy() { PostQuitMessage(0); }
|
||||
virtual void OnClose() { Destroy(); }
|
||||
/*
|
||||
virtual LRESULT OnHelp(LPHELPINFO helpInfo) { OnHelp(); };
|
||||
virtual LRESULT OnHelp(LPHELPINFO helpInfo) { OnHelp(); }
|
||||
virtual LRESULT OnHelp() {};
|
||||
virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
|
||||
virtual void OnOK() {};
|
||||
|
||||
+1
-1
@@ -95,7 +95,7 @@ FString GetModuleDirPrefix()
|
||||
FString s;
|
||||
if (MyGetModuleFileName(s))
|
||||
{
|
||||
int pos = s.ReverseFind(FCHAR_PATH_SEPARATOR);
|
||||
int pos = s.ReverseFind_PathSepar();
|
||||
if (pos >= 0)
|
||||
{
|
||||
s.DeleteFrom(pos + 1);
|
||||
|
||||
+8
-2
@@ -13,17 +13,23 @@ namespace NDLL {
|
||||
#else
|
||||
#define My_GetProcAddress(module, procName) ::GetProcAddress(module, procName)
|
||||
#endif
|
||||
|
||||
|
||||
/* Win32: Don't call CLibrary::Free() and FreeLibrary() from another
|
||||
FreeLibrary() code: detaching code in DLL entry-point or in
|
||||
destructors of global objects in DLL module. */
|
||||
|
||||
class CLibrary
|
||||
{
|
||||
HMODULE _module;
|
||||
|
||||
// CLASS_NO_COPY(CLibrary);
|
||||
public:
|
||||
CLibrary(): _module(NULL) {};
|
||||
~CLibrary() { Free(); }
|
||||
|
||||
operator HMODULE() const { return _module; }
|
||||
HMODULE* operator&() { return &_module; }
|
||||
bool IsLoaded() const { return (_module != NULL); };
|
||||
bool IsLoaded() const { return (_module != NULL); }
|
||||
|
||||
void Attach(HMODULE m)
|
||||
{
|
||||
|
||||
@@ -42,20 +42,25 @@ static bool MyFormatMessage(DWORD errorCode, UString &message)
|
||||
|
||||
UString MyFormatMessage(DWORD errorCode)
|
||||
{
|
||||
UString message;
|
||||
if (!MyFormatMessage(errorCode, message))
|
||||
UString m;
|
||||
if (!MyFormatMessage(errorCode, m) || m.IsEmpty())
|
||||
{
|
||||
wchar_t s[16];
|
||||
char s[16];
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
unsigned t = errorCode & 0xF;
|
||||
errorCode >>= 4;
|
||||
s[7 - i] = (wchar_t)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
|
||||
s[7 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
|
||||
}
|
||||
s[8] = '\0';
|
||||
message = (UString)L"Error #" + s;
|
||||
s[8] = 0;
|
||||
m.AddAscii("Error #");
|
||||
m.AddAscii(s);
|
||||
}
|
||||
return message;
|
||||
else if (m.Len() >= 2
|
||||
&& m[m.Len() - 1] == 0x0A
|
||||
&& m[m.Len() - 2] == 0x0D)
|
||||
m.DeleteFrom(m.Len() - 2);
|
||||
return m;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
+154
-47
@@ -86,9 +86,9 @@ bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const
|
||||
#ifdef WIN_LONG_PATH
|
||||
if (hDir == INVALID_HANDLE_VALUE && USE_SUPER_PATH)
|
||||
{
|
||||
UString longPath;
|
||||
if (GetSuperPath(path, longPath, USE_MAIN_PATH))
|
||||
hDir = ::CreateFileW(longPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
UString superPath;
|
||||
if (GetSuperPath(path, superPath, USE_MAIN_PATH))
|
||||
hDir = ::CreateFileW(superPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
}
|
||||
#endif
|
||||
@@ -119,9 +119,9 @@ bool SetFileAttrib(CFSTR path, DWORD attrib)
|
||||
#ifdef WIN_LONG_PATH
|
||||
if (USE_SUPER_PATH)
|
||||
{
|
||||
UString longPath;
|
||||
if (GetSuperPath(path, longPath, USE_MAIN_PATH))
|
||||
return BOOLToBool(::SetFileAttributesW(longPath, attrib));
|
||||
UString superPath;
|
||||
if (GetSuperPath(path, superPath, USE_MAIN_PATH))
|
||||
return BOOLToBool(::SetFileAttributesW(superPath, attrib));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -145,9 +145,9 @@ bool RemoveDir(CFSTR path)
|
||||
#ifdef WIN_LONG_PATH
|
||||
if (USE_SUPER_PATH)
|
||||
{
|
||||
UString longPath;
|
||||
if (GetSuperPath(path, longPath, USE_MAIN_PATH))
|
||||
return BOOLToBool(::RemoveDirectoryW(longPath));
|
||||
UString superPath;
|
||||
if (GetSuperPath(path, superPath, USE_MAIN_PATH))
|
||||
return BOOLToBool(::RemoveDirectoryW(superPath));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -226,6 +226,29 @@ bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName)
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
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
|
||||
|
||||
C:\folder - OK
|
||||
C:\folder\ - OK
|
||||
|
||||
\\Server\nonExistent - ERROR_BAD_NETPATH
|
||||
\\Server\Share_Readonly - ERROR_ACCESS_DENIED
|
||||
\\Server\Share - ERROR_ALREADY_EXISTS
|
||||
|
||||
\\Server\Share_NTFS_drive - ERROR_ACCESS_DENIED
|
||||
\\Server\Share_FAT_drive - ERROR_ALREADY_EXISTS
|
||||
*/
|
||||
|
||||
bool CreateDir(CFSTR path)
|
||||
{
|
||||
#ifndef _UNICODE
|
||||
@@ -243,56 +266,127 @@ bool CreateDir(CFSTR path)
|
||||
#ifdef WIN_LONG_PATH
|
||||
if ((!USE_MAIN_PATH || ::GetLastError() != ERROR_ALREADY_EXISTS) && USE_SUPER_PATH)
|
||||
{
|
||||
UString longPath;
|
||||
if (GetSuperPath(path, longPath, USE_MAIN_PATH))
|
||||
return BOOLToBool(::CreateDirectoryW(longPath, NULL));
|
||||
UString superPath;
|
||||
if (GetSuperPath(path, superPath, USE_MAIN_PATH))
|
||||
return BOOLToBool(::CreateDirectoryW(superPath, NULL));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CreateComplexDir(CFSTR _aPathName)
|
||||
/*
|
||||
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 */
|
||||
|
||||
static bool CreateDir2(CFSTR path)
|
||||
{
|
||||
FString pathName = _aPathName;
|
||||
int pos = pathName.ReverseFind(FCHAR_PATH_SEPARATOR);
|
||||
if (pos > 0 && (unsigned)pos == pathName.Len() - 1)
|
||||
#ifndef _UNICODE
|
||||
if (!g_IsNT)
|
||||
{
|
||||
if (pathName.Len() == 3 && pathName[1] == L':')
|
||||
return true; // Disk folder;
|
||||
pathName.Delete(pos);
|
||||
if (::CreateDirectory(fs2fas(path), NULL))
|
||||
return true;
|
||||
}
|
||||
const FString pathName2 = pathName;
|
||||
pos = pathName.Len();
|
||||
else
|
||||
#endif
|
||||
{
|
||||
IF_USE_MAIN_PATH
|
||||
if (::CreateDirectoryW(fs2us(path), NULL))
|
||||
return true;
|
||||
#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))
|
||||
return true;
|
||||
if (::GetLastError() != ERROR_ALREADY_EXISTS)
|
||||
return false;
|
||||
NFind::CFileInfo fi;
|
||||
if (!fi.Find(us2fs(superPath)))
|
||||
return false;
|
||||
return fi.IsDir();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (::GetLastError() != ERROR_ALREADY_EXISTS)
|
||||
return false;
|
||||
NFind::CFileInfo fi;
|
||||
if (!fi.Find(path))
|
||||
return false;
|
||||
return fi.IsDir();
|
||||
}
|
||||
|
||||
bool CreateComplexDir(CFSTR _path)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
{
|
||||
DWORD attrib = NFind::GetFileAttrib(_path);
|
||||
if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef UNDER_CE
|
||||
|
||||
if (IsDriveRootPath_SuperAllowed(_path))
|
||||
return false;
|
||||
|
||||
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)
|
||||
return true;
|
||||
path.DeleteBack();
|
||||
}
|
||||
|
||||
const FString path2 = path;
|
||||
pos = path.Len();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (CreateDir(pathName))
|
||||
if (CreateDir2(path))
|
||||
break;
|
||||
if (::GetLastError() == ERROR_ALREADY_EXISTS)
|
||||
{
|
||||
NFind::CFileInfo fileInfo;
|
||||
if (!fileInfo.Find(pathName)) // For network folders
|
||||
return true;
|
||||
if (!fileInfo.IsDir())
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
pos = pathName.ReverseFind(FCHAR_PATH_SEPARATOR);
|
||||
return false;
|
||||
pos = path.ReverseFind_PathSepar();
|
||||
if (pos < 0 || pos == 0)
|
||||
return false;
|
||||
if (pathName[pos - 1] == L':')
|
||||
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
if (pos == 1 && IS_PATH_SEPAR(path[0]))
|
||||
return false;
|
||||
pathName.DeleteFrom(pos);
|
||||
if (prefixSize >= (unsigned)pos + 1)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
path.DeleteFrom(pos);
|
||||
}
|
||||
|
||||
while (pos < (int)pathName2.Len())
|
||||
while (pos < (int)path2.Len())
|
||||
{
|
||||
pos = pathName2.Find(FCHAR_PATH_SEPARATOR, pos + 1);
|
||||
if (pos < 0)
|
||||
pos = pathName2.Len();
|
||||
pathName.SetFrom(pathName2, pos);
|
||||
if (!CreateDir(pathName))
|
||||
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))
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -301,8 +395,19 @@ bool CreateComplexDir(CFSTR _aPathName)
|
||||
|
||||
bool DeleteFileAlways(CFSTR path)
|
||||
{
|
||||
if (!SetFileAttrib(path, 0))
|
||||
return false;
|
||||
/* 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))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef _UNICODE
|
||||
if (!g_IsNT)
|
||||
{
|
||||
@@ -312,15 +417,17 @@ bool DeleteFileAlways(CFSTR path)
|
||||
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)))
|
||||
return true;
|
||||
#ifdef WIN_LONG_PATH
|
||||
if (USE_SUPER_PATH)
|
||||
{
|
||||
UString longPath;
|
||||
if (GetSuperPath(path, longPath, USE_MAIN_PATH))
|
||||
return BOOLToBool(::DeleteFileW(longPath));
|
||||
UString superPath;
|
||||
if (GetSuperPath(path, superPath, USE_MAIN_PATH))
|
||||
return BOOLToBool(::DeleteFileW(superPath));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -346,7 +453,7 @@ bool RemoveDirWithSubItems(const FString &path)
|
||||
if (needRemoveSubItems)
|
||||
{
|
||||
FString s = path;
|
||||
s += FCHAR_PATH_SEPARATOR;
|
||||
s.Add_PathSepar();
|
||||
unsigned prefixSize = s.Len();
|
||||
s += FCHAR_ANY_MASK;
|
||||
NFind::CEnumerator enumerator(s);
|
||||
@@ -430,7 +537,7 @@ bool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName
|
||||
bool res = MyGetFullPathName(path, resDirPrefix);
|
||||
if (!res)
|
||||
resDirPrefix = path;
|
||||
int pos = resDirPrefix.ReverseFind(FCHAR_PATH_SEPARATOR);
|
||||
int pos = resDirPrefix.ReverseFind_PathSepar();
|
||||
resFileName = resDirPrefix.Ptr(pos + 1);
|
||||
resDirPrefix.DeleteFrom(pos + 1);
|
||||
return res;
|
||||
@@ -480,7 +587,7 @@ static bool CreateTempFile(CFSTR prefix, bool addRandom, FString &path, NIO::COu
|
||||
{
|
||||
unsigned t = value & 0xF;
|
||||
value >>= 4;
|
||||
s[k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
|
||||
s[k] = (FChar)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
|
||||
}
|
||||
s[k] = '\0';
|
||||
if (outFile)
|
||||
|
||||
@@ -24,7 +24,14 @@ bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName);
|
||||
|
||||
bool RemoveDir(CFSTR path);
|
||||
bool CreateDir(CFSTR path);
|
||||
|
||||
/* CreateComplexDir returns true, if directory can contain files after the call (two cases):
|
||||
1) the directory already exists (network shares and drive paths are supported)
|
||||
2) the directory was created
|
||||
path can be WITH or WITHOUT trailing path separator. */
|
||||
|
||||
bool CreateComplexDir(CFSTR path);
|
||||
|
||||
bool DeleteFileAlways(CFSTR name);
|
||||
bool RemoveDirWithSubItems(const FString &path);
|
||||
|
||||
|
||||
+236
-81
@@ -2,13 +2,14 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "FileFind.h"
|
||||
#include "FileIO.h"
|
||||
#include "FileName.h"
|
||||
#ifndef _UNICODE
|
||||
#include "../Common/StringConvert.h"
|
||||
#endif
|
||||
|
||||
#include "FileFind.h"
|
||||
#include "FileIO.h"
|
||||
#include "FileName.h"
|
||||
|
||||
#ifndef _UNICODE
|
||||
extern bool g_IsNT;
|
||||
#endif
|
||||
@@ -58,9 +59,9 @@ bool CFileInfo::IsDots() const throw()
|
||||
{
|
||||
if (!IsDir() || Name.IsEmpty())
|
||||
return false;
|
||||
if (Name[0] != FTEXT('.'))
|
||||
if (Name[0] != '.')
|
||||
return false;
|
||||
return Name.Len() == 1 || (Name.Len() == 2 && Name[1] == FTEXT('.'));
|
||||
return Name.Len() == 1 || (Name.Len() == 2 && Name[1] == '.');
|
||||
}
|
||||
|
||||
#define WIN_FD_TO_MY_FI(fi, fd) \
|
||||
@@ -114,6 +115,32 @@ bool CFindFileBase::Close() throw()
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
WinXP-64 FindFirstFile():
|
||||
"" - ERROR_PATH_NOT_FOUND
|
||||
folder\ - ERROR_FILE_NOT_FOUND
|
||||
\ - ERROR_FILE_NOT_FOUND
|
||||
c:\ - ERROR_FILE_NOT_FOUND
|
||||
c: - ERROR_FILE_NOT_FOUND, if current dir is ROOT ( c:\ )
|
||||
c: - OK, if current dir is NOT ROOT ( c:\folder )
|
||||
folder - OK
|
||||
|
||||
\\ - ERROR_INVALID_NAME
|
||||
\\Server - ERROR_INVALID_NAME
|
||||
\\Server\ - ERROR_INVALID_NAME
|
||||
|
||||
\\Server\Share - ERROR_BAD_NETPATH
|
||||
\\Server\Share\ - ERROR_FILE_NOT_FOUND
|
||||
|
||||
\\?\UNC\Server\Share - ERROR_INVALID_NAME
|
||||
\\?\UNC\Server\Share\ - ERROR_FILE_NOT_FOUND
|
||||
|
||||
\\Server\Share_RootDrive - ERROR_INVALID_NAME
|
||||
\\Server\Share_RootDrive\ - ERROR_INVALID_NAME
|
||||
|
||||
c:\* - ERROR_FILE_NOT_FOUND, if thare are no item in that folder
|
||||
*/
|
||||
|
||||
bool CFindFile::FindFirst(CFSTR path, CFileInfo &fi)
|
||||
{
|
||||
if (!Close())
|
||||
@@ -137,9 +164,9 @@ bool CFindFile::FindFirst(CFSTR path, CFileInfo &fi)
|
||||
#ifdef WIN_LONG_PATH
|
||||
if (_handle == INVALID_HANDLE_VALUE && USE_SUPER_PATH)
|
||||
{
|
||||
UString longPath;
|
||||
if (GetSuperPath(path, longPath, USE_MAIN_PATH))
|
||||
_handle = ::FindFirstFileW(longPath, &fd);
|
||||
UString superPath;
|
||||
if (GetSuperPath(path, superPath, USE_MAIN_PATH))
|
||||
_handle = ::FindFirstFileW(superPath, &fd);
|
||||
}
|
||||
#endif
|
||||
if (_handle == INVALID_HANDLE_VALUE)
|
||||
@@ -189,24 +216,51 @@ struct CFindStreamLoader
|
||||
|
||||
bool CStreamInfo::IsMainStream() const throw()
|
||||
{
|
||||
return Name == L"::$DATA";
|
||||
return StringsAreEqualNoCase_Ascii(Name, "::$DATA");
|
||||
};
|
||||
|
||||
UString CStreamInfo::GetReducedName() const
|
||||
{
|
||||
// remove ":$DATA" postfix, but keep postfix, if Name is "::$DATA"
|
||||
UString s = Name;
|
||||
if (s.Len() >= 6)
|
||||
if (wcscmp(s.RightPtr(6), L":$DATA") == 0)
|
||||
s.DeleteFrom(s.Len() - 6);
|
||||
if (s.Len() > 6 + 1 && StringsAreEqualNoCase_Ascii(s.RightPtr(6), ":$DATA"))
|
||||
s.DeleteFrom(s.Len() - 6);
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
UString CStreamInfo::GetReducedName2() const
|
||||
{
|
||||
UString s = GetReducedName();
|
||||
if (!s.IsEmpty() && s[0] == ':')
|
||||
s.Delete(0);
|
||||
return s;
|
||||
}
|
||||
*/
|
||||
|
||||
static void Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(const MY_WIN32_FIND_STREAM_DATA &sd, CStreamInfo &si)
|
||||
{
|
||||
si.Size = sd.StreamSize.QuadPart;
|
||||
si.Name = sd.cStreamName;
|
||||
}
|
||||
|
||||
/*
|
||||
WinXP-64 FindFirstStream():
|
||||
"" - ERROR_PATH_NOT_FOUND
|
||||
folder\ - OK
|
||||
folder - OK
|
||||
\ - OK
|
||||
c:\ - OK
|
||||
c: - OK, if current dir is ROOT ( c:\ )
|
||||
c: - OK, if current dir is NOT ROOT ( c:\folder )
|
||||
\\Server\Share - OK
|
||||
\\Server\Share\ - OK
|
||||
|
||||
\\ - ERROR_INVALID_NAME
|
||||
\\Server - ERROR_INVALID_NAME
|
||||
\\Server\ - ERROR_INVALID_NAME
|
||||
*/
|
||||
|
||||
bool CFindStream::FindFirst(CFSTR path, CStreamInfo &si)
|
||||
{
|
||||
if (!Close())
|
||||
@@ -218,6 +272,7 @@ bool CFindStream::FindFirst(CFSTR path, CStreamInfo &si)
|
||||
}
|
||||
{
|
||||
MY_WIN32_FIND_STREAM_DATA sd;
|
||||
SetLastError(0);
|
||||
IF_USE_MAIN_PATH
|
||||
_handle = g_FindFirstStreamW(fs2us(path), My_FindStreamInfoStandard, &sd, 0);
|
||||
if (_handle == INVALID_HANDLE_VALUE)
|
||||
@@ -228,9 +283,9 @@ bool CFindStream::FindFirst(CFSTR path, CStreamInfo &si)
|
||||
#ifdef WIN_LONG_PATH
|
||||
if (USE_SUPER_PATH)
|
||||
{
|
||||
UString longPath;
|
||||
if (GetSuperPath(path, longPath, USE_MAIN_PATH))
|
||||
_handle = g_FindFirstStreamW(longPath, My_FindStreamInfoStandard, &sd, 0);
|
||||
UString superPath;
|
||||
if (GetSuperPath(path, superPath, USE_MAIN_PATH))
|
||||
_handle = g_FindFirstStreamW(superPath, My_FindStreamInfoStandard, &sd, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -278,7 +333,7 @@ bool CStreamEnumerator::Next(CStreamInfo &si, bool &found)
|
||||
|
||||
#define MY_CLEAR_FILETIME(ft) ft.dwLowDateTime = ft.dwHighDateTime = 0;
|
||||
|
||||
void CFileInfoBase::Clear() throw()
|
||||
void CFileInfoBase::ClearBase() throw()
|
||||
{
|
||||
Size = 0;
|
||||
MY_CLEAR_FILETIME(CTime);
|
||||
@@ -289,43 +344,83 @@ void CFileInfoBase::Clear() throw()
|
||||
IsDevice = false;
|
||||
}
|
||||
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
/*
|
||||
WinXP-64 GetFileAttributes():
|
||||
If the function fails, it returns INVALID_FILE_ATTRIBUTES and use GetLastError() to get error code
|
||||
|
||||
static int FindAltStreamColon(CFSTR path)
|
||||
\ - OK
|
||||
C:\ - OK, if there is such drive,
|
||||
D:\ - ERROR_PATH_NOT_FOUND, if there is no such drive,
|
||||
|
||||
C:\folder - OK
|
||||
C:\folder\ - OK
|
||||
C:\folderBad - ERROR_FILE_NOT_FOUND
|
||||
|
||||
\\Server\BadShare - ERROR_BAD_NETPATH
|
||||
\\Server\Share - WORKS OK, but MSDN says:
|
||||
GetFileAttributes for a network share, the function fails, and GetLastError
|
||||
returns ERROR_BAD_NETPATH. You must specify a path to a subfolder on that share.
|
||||
*/
|
||||
|
||||
DWORD GetFileAttrib(CFSTR path)
|
||||
{
|
||||
for (int i = 0;; i++)
|
||||
#ifndef _UNICODE
|
||||
if (!g_IsNT)
|
||||
return ::GetFileAttributes(fs2fas(path));
|
||||
else
|
||||
#endif
|
||||
{
|
||||
FChar c = path[i];
|
||||
if (c == 0)
|
||||
return -1;
|
||||
if (c == ':')
|
||||
IF_USE_MAIN_PATH
|
||||
{
|
||||
if (path[i + 1] == '\\')
|
||||
if (i == 1 || (i > 1 && path[i - 2] == '\\'))
|
||||
{
|
||||
wchar_t c0 = path[i - 1];
|
||||
if (c0 >= 'a' && c0 <= 'z' ||
|
||||
c0 >= 'A' && c0 <= 'Z')
|
||||
continue;
|
||||
}
|
||||
return i;
|
||||
DWORD dw = ::GetFileAttributesW(fs2us(path));
|
||||
if (dw != INVALID_FILE_ATTRIBUTES)
|
||||
return dw;
|
||||
}
|
||||
#ifdef WIN_LONG_PATH
|
||||
if (USE_SUPER_PATH)
|
||||
{
|
||||
UString superPath;
|
||||
if (GetSuperPath(path, superPath, USE_MAIN_PATH))
|
||||
return ::GetFileAttributesW(superPath);
|
||||
}
|
||||
#endif
|
||||
return INVALID_FILE_ATTRIBUTES;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/* if path is "c:" or "c::" then CFileInfo::Find() returns name of current folder for that disk
|
||||
so instead of absolute path we have relative path in Name. That is not good in some calls */
|
||||
|
||||
/* In CFileInfo::Find() we want to support same names for alt streams as in CreateFile(). */
|
||||
|
||||
/* CFileInfo::Find()
|
||||
We alow the following paths (as FindFirstFile):
|
||||
C:\folder
|
||||
c: - if current dir is NOT ROOT ( c:\folder )
|
||||
|
||||
also we support paths that are not supported by FindFirstFile:
|
||||
\
|
||||
\\.\c:
|
||||
c:\ - Name will be without tail slash ( c: )
|
||||
\\?\c:\ - Name will be without tail slash ( c: )
|
||||
\\Server\Share
|
||||
\\?\UNC\Server\Share
|
||||
|
||||
c:\folder:stream - Name = folder:stream
|
||||
c:\:stream - Name = :stream
|
||||
c::stream - Name = c::stream
|
||||
*/
|
||||
|
||||
bool CFileInfo::Find(CFSTR path)
|
||||
{
|
||||
#ifdef SUPPORT_DEVICE_FILE
|
||||
if (IsDevicePath(path))
|
||||
{
|
||||
Clear();
|
||||
ClearBase();
|
||||
Name = path + 4;
|
||||
|
||||
IsDevice = true;
|
||||
if (/* path[0] == '\\' && path[1] == '\\' && path[2] == '.' && path[3] == '\\' && */
|
||||
path[5] == ':' && path[6] == 0)
|
||||
|
||||
if (NName::IsDrivePath2(path + 4) && path[6] == 0)
|
||||
{
|
||||
FChar drive[4] = { path[4], ':', '\\', 0 };
|
||||
UInt64 clusterSize, totalSize, freeSize;
|
||||
@@ -350,16 +445,37 @@ bool CFileInfo::Find(CFSTR path)
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
|
||||
int colonPos = FindAltStreamColon(path);
|
||||
if (colonPos >= 0)
|
||||
if (colonPos >= 0 && path[(unsigned)colonPos + 1] != 0)
|
||||
{
|
||||
UString streamName = fs2us(path + (unsigned)colonPos);
|
||||
FString filePath = path;
|
||||
filePath.DeleteFrom(colonPos);
|
||||
streamName += L":$DATA"; // change it!!!!
|
||||
if (Find(filePath))
|
||||
/* we allow both cases:
|
||||
name:stream
|
||||
name:stream:$DATA
|
||||
*/
|
||||
const unsigned kPostfixSize = 6;
|
||||
if (streamName.Len() <= kPostfixSize
|
||||
|| !StringsAreEqualNoCase_Ascii(streamName.RightPtr(kPostfixSize), ":$DATA"))
|
||||
streamName += L":$DATA";
|
||||
|
||||
bool isOk = true;
|
||||
|
||||
if (IsDrivePath2(filePath) &&
|
||||
(colonPos == 2 || colonPos == 3 && filePath[2] == '\\'))
|
||||
{
|
||||
// if (IsDir())
|
||||
Attrib &= ~FILE_ATTRIBUTE_DIRECTORY;
|
||||
// FindFirstFile doesn't work for "c:\" and for "c:" (if current dir is ROOT)
|
||||
ClearBase();
|
||||
Name.Empty();
|
||||
if (colonPos == 2)
|
||||
Name = filePath;
|
||||
}
|
||||
else
|
||||
isOk = Find(filePath);
|
||||
|
||||
if (isOk)
|
||||
{
|
||||
Attrib &= ~(FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
|
||||
Size = 0;
|
||||
CStreamEnumerator enumerator(filePath);
|
||||
for (;;)
|
||||
@@ -373,10 +489,12 @@ bool CFileInfo::Find(CFSTR path)
|
||||
::SetLastError(ERROR_FILE_NOT_FOUND);
|
||||
return false;
|
||||
}
|
||||
if (si.Name.IsEqualToNoCase(streamName))
|
||||
if (si.Name.IsEqualTo_NoCase(streamName))
|
||||
{
|
||||
// we delete postfix, if alt stream name is not "::$DATA"
|
||||
if (si.Name.Len() > kPostfixSize + 1)
|
||||
si.Name.DeleteFrom(si.Name.Len() - kPostfixSize);
|
||||
Name += us2fs(si.Name);
|
||||
Name.DeleteFrom(Name.Len() - 6);
|
||||
Size = si.Size;
|
||||
IsAltStream = true;
|
||||
return true;
|
||||
@@ -390,7 +508,8 @@ bool CFileInfo::Find(CFSTR path)
|
||||
CFindFile finder;
|
||||
if (finder.FindFirst(path, *this))
|
||||
return true;
|
||||
#ifdef _WIN32
|
||||
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
{
|
||||
DWORD lastError = GetLastError();
|
||||
if (lastError == ERROR_BAD_NETPATH ||
|
||||
@@ -398,33 +517,68 @@ bool CFileInfo::Find(CFSTR path)
|
||||
lastError == ERROR_INVALID_NAME // for "\\SERVER\shared" paths that are translated to "\\?\UNC\SERVER\shared"
|
||||
)
|
||||
{
|
||||
unsigned len = MyStringLen(path);
|
||||
if (len > 2 && path[0] == '\\' && path[1] == '\\')
|
||||
unsigned rootSize = 0;
|
||||
if (IsSuperPath(path))
|
||||
rootSize = kSuperPathPrefixSize;
|
||||
if (IS_PATH_SEPAR(path[0]) && path[1] == 0)
|
||||
{
|
||||
int startPos = 2;
|
||||
if (len > kSuperUncPathPrefixSize && IsSuperUncPath(path))
|
||||
startPos = kSuperUncPathPrefixSize;
|
||||
int pos = FindCharPosInString(path + startPos, FTEXT('\\'));
|
||||
if (pos >= 0)
|
||||
DWORD attrib = GetFileAttrib(path);
|
||||
if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)
|
||||
{
|
||||
pos += startPos + 1;
|
||||
len -= pos;
|
||||
int pos2 = FindCharPosInString(path + pos, FTEXT('\\'));
|
||||
if (pos2 < 0 || pos2 == (int)len - 1)
|
||||
ClearBase();
|
||||
Name.Empty();
|
||||
Attrib = attrib;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (NName::IsDrivePath(path + rootSize) && path[rootSize + 3] == 0)
|
||||
{
|
||||
DWORD attrib = GetFileAttrib(path);
|
||||
if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)
|
||||
{
|
||||
ClearBase();
|
||||
Attrib = attrib;
|
||||
Name = path + rootSize;
|
||||
Name.DeleteFrom(2); // we don't need backslash (C:)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned prefixSize = GetNetworkServerPrefixSize(path);
|
||||
if (prefixSize > 0 && path[prefixSize] != 0)
|
||||
{
|
||||
if (NName::FindSepar(path + prefixSize) < 0)
|
||||
{
|
||||
FString s = path;
|
||||
if (pos2 < 0)
|
||||
{
|
||||
pos2 = len;
|
||||
s += FTEXT('\\');
|
||||
}
|
||||
s.Add_PathSepar();
|
||||
s += FCHAR_ANY_MASK;
|
||||
|
||||
bool isOK = false;
|
||||
if (finder.FindFirst(s, *this))
|
||||
{
|
||||
if (Name == FTEXT("."))
|
||||
{
|
||||
Name.SetFrom(s.Ptr(pos), pos2);
|
||||
Name = path + prefixSize;;
|
||||
return true;
|
||||
}
|
||||
isOK = true;
|
||||
/* if "\\server\share" maps to root folder "d:\", there is no "." item.
|
||||
But it's possible that there are another items */
|
||||
}
|
||||
{
|
||||
DWORD attrib = GetFileAttrib(path);
|
||||
if (isOK || attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)
|
||||
{
|
||||
ClearBase();
|
||||
if (attrib != INVALID_FILE_ATTRIBUTES)
|
||||
Attrib = attrib;
|
||||
else
|
||||
SetAsDir();
|
||||
Name = path + prefixSize;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
::SetLastError(lastError);
|
||||
}
|
||||
}
|
||||
@@ -432,6 +586,7 @@ bool CFileInfo::Find(CFSTR path)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -446,12 +601,14 @@ bool DoesDirExist(CFSTR name)
|
||||
CFileInfo fi;
|
||||
return fi.Find(name) && fi.IsDir();
|
||||
}
|
||||
|
||||
bool DoesFileOrDirExist(CFSTR name)
|
||||
{
|
||||
CFileInfo fi;
|
||||
return fi.Find(name);
|
||||
}
|
||||
|
||||
|
||||
bool CEnumerator::NextAny(CFileInfo &fi)
|
||||
{
|
||||
if (_findFile.IsHandleAllocated())
|
||||
@@ -509,9 +666,9 @@ HANDLE CFindChangeNotification::FindFirst(CFSTR path, bool watchSubtree, DWORD n
|
||||
#ifdef WIN_LONG_PATH
|
||||
if (!IsHandleAllocated())
|
||||
{
|
||||
UString longPath;
|
||||
if (GetSuperPath(path, longPath, USE_MAIN_PATH))
|
||||
_handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter);
|
||||
UString superPath;
|
||||
if (GetSuperPath(path, superPath, USE_MAIN_PATH))
|
||||
_handle = ::FindFirstChangeNotificationW(superPath, BoolToBOOL(watchSubtree), notifyFilter);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -530,23 +687,22 @@ bool MyGetLogicalDriveStrings(CObjectVector<FString> &driveStrings)
|
||||
UINT32 size = GetLogicalDriveStrings(0, NULL);
|
||||
if (size == 0)
|
||||
return false;
|
||||
AString buf;
|
||||
UINT32 newSize = GetLogicalDriveStrings(size, buf.GetBuffer(size));
|
||||
CObjArray<char> buf(size);
|
||||
UINT32 newSize = GetLogicalDriveStrings(size, buf);
|
||||
if (newSize == 0 || newSize > size)
|
||||
return false;
|
||||
AString s;
|
||||
UINT32 prev = 0;
|
||||
for (UINT32 i = 0; i < newSize; i++)
|
||||
{
|
||||
char c = buf[i];
|
||||
if (c == '\0')
|
||||
if (buf[i] == 0)
|
||||
{
|
||||
s = buf + prev;
|
||||
prev = i + 1;
|
||||
driveStrings.Add(fas2fs(s));
|
||||
s.Empty();
|
||||
}
|
||||
else
|
||||
s += c;
|
||||
}
|
||||
return s.IsEmpty();
|
||||
return prev == newSize;;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -554,23 +710,22 @@ bool MyGetLogicalDriveStrings(CObjectVector<FString> &driveStrings)
|
||||
UINT32 size = GetLogicalDriveStringsW(0, NULL);
|
||||
if (size == 0)
|
||||
return false;
|
||||
UString buf;
|
||||
UINT32 newSize = GetLogicalDriveStringsW(size, buf.GetBuffer(size));
|
||||
CObjArray<wchar_t> buf(size);
|
||||
UINT32 newSize = GetLogicalDriveStringsW(size, buf);
|
||||
if (newSize == 0 || newSize > size)
|
||||
return false;
|
||||
UString s;
|
||||
UINT32 prev = 0;
|
||||
for (UINT32 i = 0; i < newSize; i++)
|
||||
{
|
||||
WCHAR c = buf[i];
|
||||
if (c == L'\0')
|
||||
if (buf[i] == 0)
|
||||
{
|
||||
s = buf + prev;
|
||||
prev = i + 1;
|
||||
driveStrings.Add(us2fs(s));
|
||||
s.Empty();
|
||||
}
|
||||
else
|
||||
s += c;
|
||||
}
|
||||
return s.IsEmpty();
|
||||
return prev == newSize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,8 +41,8 @@ public:
|
||||
#endif
|
||||
*/
|
||||
|
||||
CFileInfoBase() { Clear(); }
|
||||
void Clear() throw();
|
||||
CFileInfoBase() { ClearBase(); }
|
||||
void ClearBase() throw();
|
||||
|
||||
void SetAsDir() { Attrib = FILE_ATTRIBUTE_DIRECTORY; }
|
||||
|
||||
@@ -68,7 +68,7 @@ struct CFileInfo: public CFileInfoBase
|
||||
#endif
|
||||
|
||||
bool IsDots() const throw();
|
||||
bool Find(CFSTR wildcard);
|
||||
bool Find(CFSTR path);
|
||||
};
|
||||
|
||||
class CFindFileBase
|
||||
@@ -96,7 +96,8 @@ struct CStreamInfo
|
||||
UString Name;
|
||||
UInt64 Size;
|
||||
|
||||
UString GetReducedName() const;
|
||||
UString GetReducedName() const; // returns ":Name"
|
||||
// UString GetReducedName2() const; // returns "Name"
|
||||
bool IsMainStream() const throw();
|
||||
};
|
||||
|
||||
@@ -124,6 +125,8 @@ bool DoesFileExist(CFSTR name);
|
||||
bool DoesDirExist(CFSTR name);
|
||||
bool DoesFileOrDirExist(CFSTR name);
|
||||
|
||||
DWORD GetFileAttrib(CFSTR path);
|
||||
|
||||
class CEnumerator
|
||||
{
|
||||
CFindFile _findFile;
|
||||
|
||||
@@ -130,7 +130,7 @@ bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition
|
||||
if (low == 0xFFFFFFFF)
|
||||
if (::GetLastError() != NO_ERROR)
|
||||
return false;
|
||||
newPosition = (((UInt64)high) << 32) + low;
|
||||
newPosition = (((UInt64)(UInt32)high) << 32) + low;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -102,6 +102,8 @@ void WriteString(Byte *dest, const wchar_t *path)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
|
||||
bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink)
|
||||
{
|
||||
bool isAbs = IsAbsolutePath(path);
|
||||
@@ -175,13 +177,21 @@ bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink)
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void GetString(const Byte *p, unsigned len, UString &res)
|
||||
{
|
||||
wchar_t *s = res.GetBuffer(len);
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
s[i] = Get16(p + i * 2);
|
||||
s[len] = 0;
|
||||
res.ReleaseBuffer();
|
||||
wchar_t *s = res.GetBuf(len);
|
||||
unsigned i;
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
wchar_t c = Get16(p + i * 2);
|
||||
if (c == 0)
|
||||
break;
|
||||
s[i] = c;
|
||||
}
|
||||
s[i] = 0;
|
||||
res.ReleaseBuf_SetLen(i);
|
||||
}
|
||||
|
||||
bool CReparseAttr::Parse(const Byte *p, size_t size)
|
||||
@@ -367,7 +377,7 @@ bool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMA
|
||||
static bool CreatePrefixDirOfFile(CFSTR path)
|
||||
{
|
||||
FString path2 = path;
|
||||
int pos = path2.ReverseFind(FCHAR_PATH_SEPARATOR);
|
||||
int pos = path2.ReverseFind_PathSepar();
|
||||
if (pos < 0)
|
||||
return true;
|
||||
#ifdef _WIN32
|
||||
|
||||
+217
-75
@@ -12,13 +12,41 @@ namespace NWindows {
|
||||
namespace NFile {
|
||||
namespace NName {
|
||||
|
||||
#define IS_SEPAR(c) IS_PATH_SEPAR(c)
|
||||
|
||||
int FindSepar(const wchar_t *s) throw()
|
||||
{
|
||||
for (const wchar_t *p = s;; p++)
|
||||
{
|
||||
const wchar_t c = *p;
|
||||
if (c == 0)
|
||||
return -1;
|
||||
if (IS_SEPAR(c))
|
||||
return (int)(p - s);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef USE_UNICODE_FSTRING
|
||||
int FindSepar(const FChar *s) throw()
|
||||
{
|
||||
for (const FChar *p = s;; p++)
|
||||
{
|
||||
const FChar c = *p;
|
||||
if (c == 0)
|
||||
return -1;
|
||||
if (IS_SEPAR(c))
|
||||
return (int)(p - s);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef USE_UNICODE_FSTRING
|
||||
void NormalizeDirPathPrefix(FString &dirPath)
|
||||
{
|
||||
if (dirPath.IsEmpty())
|
||||
return;
|
||||
if (dirPath.Back() != FCHAR_PATH_SEPARATOR)
|
||||
dirPath += FCHAR_PATH_SEPARATOR;
|
||||
if (!IsPathSepar(dirPath.Back()))
|
||||
dirPath.Add_PathSepar();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -26,26 +54,51 @@ void NormalizeDirPathPrefix(UString &dirPath)
|
||||
{
|
||||
if (dirPath.IsEmpty())
|
||||
return;
|
||||
if (dirPath.Back() != WCHAR_PATH_SEPARATOR)
|
||||
dirPath += WCHAR_PATH_SEPARATOR;
|
||||
if (!IsPathSepar(dirPath.Back()))
|
||||
dirPath.Add_PathSepar();
|
||||
}
|
||||
|
||||
#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z')
|
||||
|
||||
#ifdef _WIN32
|
||||
bool IsDrivePath(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && IS_SEPAR(s[2]); }
|
||||
|
||||
bool IsAltPathPrefix(CFSTR s) throw()
|
||||
{
|
||||
unsigned len = MyStringLen(s);
|
||||
if (len == 0)
|
||||
return false;
|
||||
if (s[len - 1] != ':')
|
||||
return false;
|
||||
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
if (IsDevicePath(s))
|
||||
return false;
|
||||
if (IsSuperPath(s))
|
||||
{
|
||||
s += kSuperPathPrefixSize;
|
||||
len -= kSuperPathPrefixSize;
|
||||
}
|
||||
if (len == 2 && IsDrivePath2(s))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
|
||||
const wchar_t *kSuperPathPrefix = L"\\\\?\\";
|
||||
static const wchar_t *kSuperUncPrefix = L"\\\\?\\UNC\\";
|
||||
|
||||
#define IS_DEVICE_PATH(s) ((s)[0] == '\\' && (s)[1] == '\\' && (s)[2] == '.' && (s)[3] == '\\')
|
||||
#define IS_SUPER_PREFIX(s) ((s)[0] == '\\' && (s)[1] == '\\' && (s)[2] == '?' && (s)[3] == '\\')
|
||||
#define IS_SUPER_OR_DEVICE_PATH(s) ((s)[0] == '\\' && (s)[1] == '\\' && ((s)[2] == '?' || (s)[2] == '.') && (s)[3] == '\\')
|
||||
#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z')
|
||||
#define IS_DEVICE_PATH(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '.' && IS_SEPAR((s)[3]))
|
||||
#define IS_SUPER_PREFIX(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '?' && IS_SEPAR((s)[3]))
|
||||
#define IS_SUPER_OR_DEVICE_PATH(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && ((s)[2] == '?' || (s)[2] == '.') && IS_SEPAR((s)[3]))
|
||||
|
||||
#define IS_UNC_WITH_SLASH(s) ( \
|
||||
((s)[0] == 'U' || (s)[0] == 'u') && \
|
||||
((s)[1] == 'N' || (s)[1] == 'n') && \
|
||||
((s)[2] == 'C' || (s)[2] == 'c') && \
|
||||
(s)[3] == '\\')
|
||||
((s)[0] == 'U' || (s)[0] == 'u') \
|
||||
&& ((s)[1] == 'N' || (s)[1] == 'n') \
|
||||
&& ((s)[2] == 'C' || (s)[2] == 'c') \
|
||||
&& IS_SEPAR((s)[3]))
|
||||
|
||||
bool IsDevicePath(CFSTR s) throw()
|
||||
{
|
||||
@@ -81,50 +134,133 @@ bool IsDevicePath(CFSTR s) throw()
|
||||
}
|
||||
|
||||
bool IsSuperUncPath(CFSTR s) throw() { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); }
|
||||
|
||||
bool IsDrivePath(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == '\\'; }
|
||||
bool IsSuperPath(const wchar_t *s) throw() { return IS_SUPER_PREFIX(s); }
|
||||
bool IsSuperOrDevicePath(const wchar_t *s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); }
|
||||
// bool IsSuperUncPath(const wchar_t *s) { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); }
|
||||
|
||||
#ifndef USE_UNICODE_FSTRING
|
||||
bool IsDrivePath(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == '\\'; }
|
||||
bool IsSuperPath(CFSTR s) throw() { return IS_SUPER_PREFIX(s); }
|
||||
bool IsSuperOrDevicePath(CFSTR s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); }
|
||||
#endif // USE_UNICODE_FSTRING
|
||||
|
||||
bool IsAbsolutePath(const wchar_t *s) throw()
|
||||
bool IsNetworkPath(CFSTR s) throw()
|
||||
{
|
||||
return s[0] == WCHAR_PATH_SEPARATOR || IsDrivePath(s);
|
||||
if (!IS_SEPAR(s[0]) || !IS_SEPAR(s[1]))
|
||||
return false;
|
||||
if (IsSuperUncPath(s))
|
||||
return true;
|
||||
FChar c = s[2];
|
||||
return (c != '.' && c != '?');
|
||||
}
|
||||
|
||||
unsigned GetNetworkServerPrefixSize(CFSTR s) throw()
|
||||
{
|
||||
if (!IS_SEPAR(s[0]) || !IS_SEPAR(s[1]))
|
||||
return 0;
|
||||
unsigned prefixSize = 2;
|
||||
if (IsSuperUncPath(s))
|
||||
prefixSize = kSuperUncPathPrefixSize;
|
||||
else
|
||||
{
|
||||
FChar c = s[2];
|
||||
if (c == '.' || c == '?')
|
||||
return 0;
|
||||
}
|
||||
int pos = FindSepar(s + prefixSize);
|
||||
if (pos < 0)
|
||||
return 0;
|
||||
return prefixSize + pos + 1;
|
||||
}
|
||||
|
||||
bool IsNetworkShareRootPath(CFSTR s) throw()
|
||||
{
|
||||
unsigned prefixSize = GetNetworkServerPrefixSize(s);
|
||||
if (prefixSize == 0)
|
||||
return false;
|
||||
s += prefixSize;
|
||||
int pos = FindSepar(s);
|
||||
if (pos < 0)
|
||||
return true;
|
||||
return s[(unsigned)pos + 1] == 0;
|
||||
}
|
||||
|
||||
static const unsigned kDrivePrefixSize = 3; /* c:\ */
|
||||
|
||||
bool IsDrivePath2(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':'; }
|
||||
// bool IsDriveName2(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == 0; }
|
||||
bool IsSuperPath(const wchar_t *s) throw() { return IS_SUPER_PREFIX(s); }
|
||||
bool IsSuperOrDevicePath(const wchar_t *s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); }
|
||||
// bool IsSuperUncPath(const wchar_t *s) throw() { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); }
|
||||
|
||||
#ifndef USE_UNICODE_FSTRING
|
||||
bool IsDrivePath2(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':'; }
|
||||
// bool IsDriveName2(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == 0; }
|
||||
bool IsDrivePath(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && IS_SEPAR(s[2]); }
|
||||
bool IsSuperPath(CFSTR s) throw() { return IS_SUPER_PREFIX(s); }
|
||||
bool IsSuperOrDevicePath(CFSTR s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); }
|
||||
#endif // USE_UNICODE_FSTRING
|
||||
|
||||
/*
|
||||
bool IsDrivePath_SuperAllowed(CFSTR s)
|
||||
{
|
||||
if (IsSuperPath(s))
|
||||
s += kSuperPathPrefixSize;
|
||||
return IsDrivePath(s);
|
||||
}
|
||||
*/
|
||||
|
||||
bool IsDriveRootPath_SuperAllowed(CFSTR s) throw()
|
||||
{
|
||||
if (IsSuperPath(s))
|
||||
s += kSuperPathPrefixSize;
|
||||
return IsDrivePath(s) && s[kDrivePrefixSize] == 0;
|
||||
}
|
||||
|
||||
bool IsAbsolutePath(const wchar_t *s) throw()
|
||||
{
|
||||
return IS_SEPAR(s[0]) || IsDrivePath2(s);
|
||||
}
|
||||
|
||||
int FindAltStreamColon(CFSTR path)
|
||||
{
|
||||
unsigned i = 0;
|
||||
if (IsDrivePath2(path))
|
||||
i = 2;
|
||||
int colonPos = -1;
|
||||
for (;; i++)
|
||||
{
|
||||
FChar c = path[i];
|
||||
if (c == 0)
|
||||
return colonPos;
|
||||
if (c == ':')
|
||||
{
|
||||
if (colonPos < 0)
|
||||
colonPos = i;
|
||||
continue;
|
||||
}
|
||||
if (IS_SEPAR(c))
|
||||
colonPos = -1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef USE_UNICODE_FSTRING
|
||||
|
||||
static unsigned GetRootPrefixSize_Of_NetworkPath(CFSTR s) throw()
|
||||
static unsigned GetRootPrefixSize_Of_NetworkPath(CFSTR s)
|
||||
{
|
||||
// Network path: we look "server\path\" as root prefix
|
||||
int pos = FindCharPosInString(s, '\\');
|
||||
int pos = FindSepar(s);
|
||||
if (pos < 0)
|
||||
return 0;
|
||||
int pos2 = FindCharPosInString(s + pos + 1, '\\');
|
||||
int pos2 = FindSepar(s + (unsigned)pos + 1);
|
||||
if (pos2 < 0)
|
||||
return 0;
|
||||
return pos + pos2 + 2;
|
||||
}
|
||||
|
||||
static unsigned GetRootPrefixSize_Of_SimplePath(CFSTR s) throw()
|
||||
static unsigned GetRootPrefixSize_Of_SimplePath(CFSTR s)
|
||||
{
|
||||
if (IsDrivePath(s))
|
||||
return kDrivePrefixSize;
|
||||
if (s[0] != '\\' || s[1] != '\\')
|
||||
if (!IS_SEPAR(s[0]))
|
||||
return 0;
|
||||
if (s[1] == 0 || !IS_SEPAR(s[1]))
|
||||
return 1;
|
||||
unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2);
|
||||
return (size == 0) ? 0 : 2 + size;
|
||||
}
|
||||
|
||||
static unsigned GetRootPrefixSize_Of_SuperPath(CFSTR s) throw()
|
||||
static unsigned GetRootPrefixSize_Of_SuperPath(CFSTR s)
|
||||
{
|
||||
if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize))
|
||||
{
|
||||
@@ -132,13 +268,13 @@ static unsigned GetRootPrefixSize_Of_SuperPath(CFSTR s) throw()
|
||||
return (size == 0) ? 0 : kSuperUncPathPrefixSize + size;
|
||||
}
|
||||
// we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\"
|
||||
int pos = FindCharPosInString(s + kSuperPathPrefixSize, FCHAR_PATH_SEPARATOR);
|
||||
int pos = FindSepar(s + kSuperPathPrefixSize);
|
||||
if (pos < 0)
|
||||
return 0;
|
||||
return kSuperPathPrefixSize + pos + 1;
|
||||
}
|
||||
|
||||
unsigned GetRootPrefixSize(CFSTR s) throw()
|
||||
unsigned GetRootPrefixSize(CFSTR s)
|
||||
{
|
||||
if (IS_DEVICE_PATH(s))
|
||||
return kDevicePathPrefixSize;
|
||||
@@ -149,29 +285,31 @@ unsigned GetRootPrefixSize(CFSTR s) throw()
|
||||
|
||||
#endif // USE_UNICODE_FSTRING
|
||||
|
||||
static unsigned GetRootPrefixSize_Of_NetworkPath(const wchar_t *s) throw()
|
||||
static unsigned GetRootPrefixSize_Of_NetworkPath(const wchar_t *s)
|
||||
{
|
||||
// Network path: we look "server\path\" as root prefix
|
||||
int pos = FindCharPosInString(s, L'\\');
|
||||
int pos = FindSepar(s);
|
||||
if (pos < 0)
|
||||
return 0;
|
||||
int pos2 = FindCharPosInString(s + pos + 1, L'\\');
|
||||
int pos2 = FindSepar(s + (unsigned)pos + 1);
|
||||
if (pos2 < 0)
|
||||
return 0;
|
||||
return pos + pos2 + 2;
|
||||
}
|
||||
|
||||
static unsigned GetRootPrefixSize_Of_SimplePath(const wchar_t *s) throw()
|
||||
static unsigned GetRootPrefixSize_Of_SimplePath(const wchar_t *s)
|
||||
{
|
||||
if (IsDrivePath(s))
|
||||
return kDrivePrefixSize;
|
||||
if (s[0] != '\\' || s[1] != '\\')
|
||||
if (!IS_SEPAR(s[0]))
|
||||
return 0;
|
||||
if (s[1] == 0 || !IS_SEPAR(s[1]))
|
||||
return 1;
|
||||
unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2);
|
||||
return (size == 0) ? 0 : 2 + size;
|
||||
}
|
||||
|
||||
static unsigned GetRootPrefixSize_Of_SuperPath(const wchar_t *s) throw()
|
||||
static unsigned GetRootPrefixSize_Of_SuperPath(const wchar_t *s)
|
||||
{
|
||||
if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize))
|
||||
{
|
||||
@@ -179,7 +317,7 @@ static unsigned GetRootPrefixSize_Of_SuperPath(const wchar_t *s) throw()
|
||||
return (size == 0) ? 0 : kSuperUncPathPrefixSize + size;
|
||||
}
|
||||
// we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\"
|
||||
int pos = FindCharPosInString(s + kSuperPathPrefixSize, L'\\');
|
||||
int pos = FindSepar(s + kSuperPathPrefixSize);
|
||||
if (pos < 0)
|
||||
return 0;
|
||||
return kSuperPathPrefixSize + pos + 1;
|
||||
@@ -196,12 +334,12 @@ unsigned GetRootPrefixSize(const wchar_t *s) throw()
|
||||
|
||||
#else // _WIN32
|
||||
|
||||
bool IsAbsolutePath(const wchar_t *s) throw() { return s[0] == WCHAR_PATH_SEPARATOR }
|
||||
bool IsAbsolutePath(const wchar_t *s) { return IS_SEPAR(s[0]); }
|
||||
|
||||
#ifndef USE_UNICODE_FSTRING
|
||||
unsigned GetRootPrefixSize(CFSTR s) throw() { return s[0] == CHAR_PATH_SEPRATOR ? 1 : 0; }
|
||||
unsigned GetRootPrefixSize(CFSTR s) { return IS_SEPAR(s[0]) ? 1 : 0; }
|
||||
#endif
|
||||
unsigned GetRootPrefixSize(const wchar_t *s) throw() { return s[0] == CHAR_PATH_SEPRATOR ? 1 : 0; }
|
||||
unsigned GetRootPrefixSize(const wchar_t *s) { return IS_SEPAR(s[0]) ? 1 : 0; }
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
@@ -234,26 +372,26 @@ static bool GetCurDir(UString &path)
|
||||
static bool ResolveDotsFolders(UString &s)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
s.Replace(L'/', WCHAR_PATH_SEPARATOR);
|
||||
// s.Replace(L'/', WCHAR_PATH_SEPARATOR);
|
||||
#endif
|
||||
for (int i = 0;;)
|
||||
for (unsigned i = 0;;)
|
||||
{
|
||||
wchar_t c = s[i];
|
||||
if (c == 0)
|
||||
return true;
|
||||
if (c == '.' && (i == 0 || s[i - 1] == WCHAR_PATH_SEPARATOR))
|
||||
if (c == '.' && (i == 0 || IS_SEPAR(s[i - 1])))
|
||||
{
|
||||
wchar_t c1 = s[i + 1];
|
||||
if (c1 == '.')
|
||||
{
|
||||
wchar_t c2 = s[i + 2];
|
||||
if (c2 == WCHAR_PATH_SEPARATOR || c2 == 0)
|
||||
if (IS_SEPAR(c2) || c2 == 0)
|
||||
{
|
||||
if (i == 0)
|
||||
return false;
|
||||
int k = i - 2;
|
||||
for (; k >= 0; k--)
|
||||
if (s[k] == WCHAR_PATH_SEPARATOR)
|
||||
if (IS_SEPAR(s[(unsigned)k]))
|
||||
break;
|
||||
unsigned num;
|
||||
if (k >= 0)
|
||||
@@ -272,7 +410,7 @@ static bool ResolveDotsFolders(UString &s)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (c1 == WCHAR_PATH_SEPARATOR || c1 == 0)
|
||||
if (IS_SEPAR(c1) || c1 == 0)
|
||||
{
|
||||
unsigned num = 2;
|
||||
if (i != 0)
|
||||
@@ -308,11 +446,11 @@ static bool AreThereDotsFolders(CFSTR s)
|
||||
FChar c = s[i];
|
||||
if (c == 0)
|
||||
return false;
|
||||
if (c == '.' && (i == 0 || s[i - 1] == CHAR_PATH_SEPARATOR))
|
||||
if (c == '.' && (i == 0 || IS_SEPAR(s[i - 1])))
|
||||
{
|
||||
FChar c1 = s[i + 1];
|
||||
if (c1 == 0 || c1 == CHAR_PATH_SEPARATOR ||
|
||||
(c1 == '.' && (s[i + 2] == 0 || s[i + 2] == CHAR_PATH_SEPARATOR)))
|
||||
if (c1 == 0 || IS_SEPAR(c1) ||
|
||||
(c1 == '.' && (s[i + 2] == 0 || IS_SEPAR(s[i + 2]))))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -360,16 +498,16 @@ int GetUseSuperPathType(CFSTR s) throw()
|
||||
if (c == '.' || c == ' ')
|
||||
{
|
||||
FChar c2 = s[i + 1];
|
||||
if (c2 == 0 || c2 == CHAR_PATH_SEPARATOR)
|
||||
if (c2 == 0 || IS_SEPAR(c2))
|
||||
{
|
||||
// if it's "." or "..", it's not bad name.
|
||||
if (c == '.')
|
||||
{
|
||||
if (i == 0 || s[i - 1] == CHAR_PATH_SEPARATOR)
|
||||
if (i == 0 || IS_SEPAR(s[i - 1]))
|
||||
continue;
|
||||
if (s[i - 1] == '.')
|
||||
{
|
||||
if (i - 1 == 0 || s[i - 2] == CHAR_PATH_SEPARATOR)
|
||||
if (i - 1 == 0 || IS_SEPAR(s[i - 2]))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -431,14 +569,17 @@ static bool GetSuperPathBase(CFSTR s, UString &res)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (c == CHAR_PATH_SEPARATOR)
|
||||
if (IS_SEPAR(c))
|
||||
{
|
||||
if (s[1] == CHAR_PATH_SEPARATOR)
|
||||
if (IS_SEPAR(s[1]))
|
||||
{
|
||||
UString temp = fs2us(s + 2);
|
||||
unsigned fixedSize = GetRootPrefixSize_Of_NetworkPath(temp);
|
||||
if (fixedSize == 0) // maybe we must ignore that error to allow short network paths?
|
||||
// we ignore that error to allow short network paths server\share?
|
||||
/*
|
||||
if (fixedSize == 0)
|
||||
return false;
|
||||
*/
|
||||
UString rem = &temp[fixedSize];
|
||||
if (!ResolveDotsFolders(rem))
|
||||
return false;
|
||||
@@ -451,14 +592,17 @@ static bool GetSuperPathBase(CFSTR s, UString &res)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsDrivePath(s))
|
||||
if (IsDrivePath2(s))
|
||||
{
|
||||
UString temp = fs2us(s);
|
||||
UString rem = &temp[kDrivePrefixSize];
|
||||
unsigned prefixSize = 2;
|
||||
if (IsDrivePath(s))
|
||||
prefixSize = kDrivePrefixSize;
|
||||
UString rem = temp.Ptr(prefixSize);
|
||||
if (!ResolveDotsFolders(rem))
|
||||
return true;
|
||||
res += kSuperPathPrefix;
|
||||
temp.DeleteFrom(kDrivePrefixSize);
|
||||
temp.DeleteFrom(prefixSize);
|
||||
res += temp;
|
||||
res += rem;
|
||||
return true;
|
||||
@@ -468,8 +612,7 @@ static bool GetSuperPathBase(CFSTR s, UString &res)
|
||||
UString curDir;
|
||||
if (!GetCurDir(curDir))
|
||||
return false;
|
||||
if (curDir.Back() != WCHAR_PATH_SEPARATOR)
|
||||
curDir += WCHAR_PATH_SEPARATOR;
|
||||
NormalizeDirPathPrefix(curDir);
|
||||
|
||||
unsigned fixedSizeStart = 0;
|
||||
unsigned fixedSize = 0;
|
||||
@@ -489,10 +632,10 @@ static bool GetSuperPathBase(CFSTR s, UString &res)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (curDir[0] != CHAR_PATH_SEPARATOR || curDir[1] != CHAR_PATH_SEPARATOR)
|
||||
if (!IsPathSepar(curDir[0]) || !IsPathSepar(curDir[1]))
|
||||
return false;
|
||||
fixedSizeStart = 2;
|
||||
fixedSize = GetRootPrefixSize_Of_NetworkPath(&curDir[2]);
|
||||
fixedSize = GetRootPrefixSize_Of_NetworkPath(curDir.Ptr(2));
|
||||
if (fixedSize == 0)
|
||||
return false;
|
||||
superMarker = kSuperUncPrefix;
|
||||
@@ -500,7 +643,7 @@ static bool GetSuperPathBase(CFSTR s, UString &res)
|
||||
}
|
||||
|
||||
UString temp;
|
||||
if (c == CHAR_PATH_SEPARATOR)
|
||||
if (IS_SEPAR(c))
|
||||
{
|
||||
temp = fs2us(s + 1);
|
||||
}
|
||||
@@ -584,7 +727,7 @@ bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res)
|
||||
|
||||
#ifdef UNDER_CE
|
||||
|
||||
if (s[0] != CHAR_PATH_SEPARATOR)
|
||||
if (!IS_SEPAR(s[0]))
|
||||
{
|
||||
if (!dirPrefix)
|
||||
return false;
|
||||
@@ -614,7 +757,7 @@ bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res)
|
||||
return true;
|
||||
if (c == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0)))
|
||||
return true;
|
||||
if (c == CHAR_PATH_SEPARATOR && s[1] == CHAR_PATH_SEPARATOR)
|
||||
if (IS_SEPAR(c) && IS_SEPAR(s[1]))
|
||||
return true;
|
||||
if (IsDrivePath(s))
|
||||
return true;
|
||||
@@ -628,8 +771,7 @@ bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res)
|
||||
if (!GetCurDir(curDir))
|
||||
return false;
|
||||
}
|
||||
if (!curDir.IsEmpty() && curDir.Back() != WCHAR_PATH_SEPARATOR)
|
||||
curDir += WCHAR_PATH_SEPARATOR;
|
||||
NormalizeDirPathPrefix(curDir);
|
||||
|
||||
unsigned fixedSize = 0;
|
||||
|
||||
@@ -647,9 +789,9 @@ bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res)
|
||||
fixedSize = kDrivePrefixSize;
|
||||
else
|
||||
{
|
||||
if (curDir[0] != WCHAR_PATH_SEPARATOR || curDir[1] != WCHAR_PATH_SEPARATOR)
|
||||
if (!IsPathSepar(curDir[0]) || !IsPathSepar(curDir[1]))
|
||||
return false;
|
||||
fixedSize = GetRootPrefixSize_Of_NetworkPath(&curDir[2]);
|
||||
fixedSize = GetRootPrefixSize_Of_NetworkPath(curDir.Ptr(2));
|
||||
if (fixedSize == 0)
|
||||
return false;
|
||||
fixedSize += 2;
|
||||
@@ -659,7 +801,7 @@ bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res)
|
||||
#endif // _WIN32
|
||||
|
||||
UString temp;
|
||||
if (s[0] == CHAR_PATH_SEPARATOR)
|
||||
if (IS_SEPAR(s[0]))
|
||||
{
|
||||
temp = fs2us(s + 1);
|
||||
}
|
||||
|
||||
+46
-5
@@ -9,29 +9,70 @@ namespace NWindows {
|
||||
namespace NFile {
|
||||
namespace NName {
|
||||
|
||||
int FindSepar(const wchar_t *s) throw();
|
||||
#ifndef USE_UNICODE_FSTRING
|
||||
int FindSepar(const FChar *s) throw();
|
||||
#endif
|
||||
|
||||
void NormalizeDirPathPrefix(FString &dirPath); // ensures that it ended with '\\', if dirPath is not epmty
|
||||
void NormalizeDirPathPrefix(UString &dirPath);
|
||||
|
||||
#ifdef _WIN32
|
||||
bool IsDrivePath(const wchar_t *s) throw(); // first 3 chars are drive chars like "a:\\"
|
||||
|
||||
bool IsAltPathPrefix(CFSTR s) throw(); /* name: */
|
||||
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
|
||||
extern const wchar_t *kSuperPathPrefix; /* \\?\ */
|
||||
const unsigned kDevicePathPrefixSize = 4;
|
||||
const unsigned kSuperPathPrefixSize = 4;
|
||||
const unsigned kSuperUncPathPrefixSize = kSuperPathPrefixSize + 4;
|
||||
|
||||
bool IsDevicePath(CFSTR s) throw(); /* \\.\ */
|
||||
bool IsSuperUncPath(CFSTR s) throw();
|
||||
bool IsDevicePath(CFSTR s) throw(); /* \\.\ */
|
||||
bool IsSuperUncPath(CFSTR s) throw(); /* \\?\UNC\ */
|
||||
bool IsNetworkPath(CFSTR s) throw(); /* \\?\UNC\ or \\SERVER */
|
||||
|
||||
bool IsDrivePath(const wchar_t *s) throw();
|
||||
/* GetNetworkServerPrefixSize() returns size of server prefix:
|
||||
\\?\UNC\SERVER\
|
||||
\\SERVER\
|
||||
in another cases it returns 0
|
||||
*/
|
||||
|
||||
unsigned GetNetworkServerPrefixSize(CFSTR s) throw();
|
||||
|
||||
bool IsNetworkShareRootPath(CFSTR s) throw(); /* \\?\UNC\SERVER\share or \\SERVER\share or with slash */
|
||||
|
||||
// bool IsDrivePath_SuperAllowed(CFSTR s) throw(); // first chars are drive chars like "a:\" or "\\?\a:\"
|
||||
bool IsDriveRootPath_SuperAllowed(CFSTR s) throw(); // exact drive root path "a:\" or "\\?\a:\"
|
||||
|
||||
bool IsDrivePath2(const wchar_t *s) throw(); // first 2 chars are drive chars like "a:"
|
||||
// bool IsDriveName2(const wchar_t *s) throw(); // is drive name like "a:"
|
||||
bool IsSuperPath(const wchar_t *s) throw();
|
||||
bool IsSuperOrDevicePath(const wchar_t *s) throw();
|
||||
|
||||
#ifndef USE_UNICODE_FSTRING
|
||||
bool IsDrivePath2(CFSTR s) throw(); // first 2 chars are drive chars like "a:"
|
||||
// bool IsDriveName2(CFSTR s) throw(); // is drive name like "a:"
|
||||
bool IsDrivePath(CFSTR s) throw();
|
||||
bool IsSuperPath(CFSTR s) throw();
|
||||
bool IsSuperOrDevicePath(CFSTR s) throw();
|
||||
|
||||
/* GetRootPrefixSize() returns size of ROOT PREFIX for cases:
|
||||
\
|
||||
\\.\
|
||||
C:\
|
||||
\\?\C:\
|
||||
\\?\UNC\SERVER\Shared\
|
||||
\\SERVER\Shared\
|
||||
in another cases it returns 0
|
||||
*/
|
||||
|
||||
unsigned GetRootPrefixSize(CFSTR s) throw();
|
||||
|
||||
#endif
|
||||
|
||||
int FindAltStreamColon(CFSTR path);
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
bool IsAbsolutePath(const wchar_t *s) throw();
|
||||
@@ -44,7 +85,7 @@ const int kSuperPathType_UseOnlySuper = 1;
|
||||
const int kSuperPathType_UseMainAndSuper = 2;
|
||||
|
||||
int GetUseSuperPathType(CFSTR s) throw();
|
||||
bool GetSuperPath(CFSTR path, UString &longPath, bool onlyIfNew);
|
||||
bool GetSuperPath(CFSTR path, UString &superPath, bool onlyIfNew);
|
||||
bool GetSuperPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2, bool onlyIfNew);
|
||||
|
||||
#define USE_MAIN_PATH (__useSuperPathType != kSuperPathType_UseOnlySuper)
|
||||
|
||||
@@ -12,7 +12,7 @@ class CGlobal
|
||||
public:
|
||||
CGlobal(): _global(NULL){};
|
||||
~CGlobal() { Free(); }
|
||||
operator HGLOBAL() const { return _global; };
|
||||
operator HGLOBAL() const { return _global; }
|
||||
void Attach(HGLOBAL hGlobal)
|
||||
{
|
||||
Free();
|
||||
|
||||
+6
-2
@@ -81,14 +81,18 @@ public:
|
||||
|
||||
HMENU GetSubMenu(int pos) { return ::GetSubMenu(_menu, pos); }
|
||||
#ifndef UNDER_CE
|
||||
/*
|
||||
bool GetItemString(UINT idItem, UINT flag, CSysString &result)
|
||||
{
|
||||
result.Empty();
|
||||
int len = ::GetMenuString(_menu, idItem, 0, 0, flag);
|
||||
len = ::GetMenuString(_menu, idItem, result.GetBuffer(len + 2), len + 1, flag);
|
||||
result.ReleaseBuffer();
|
||||
int len2 = ::GetMenuString(_menu, idItem, result.GetBuf(len + 2), len + 1, flag);
|
||||
if (len > len2)
|
||||
len = len2;
|
||||
result.ReleaseBuf_CalcLen(len + 2);
|
||||
return (len != 0);
|
||||
}
|
||||
*/
|
||||
UINT GetItemID(int pos) { return ::GetMenuItemID(_menu, pos); }
|
||||
UINT GetItemState(UINT id, UINT flags) { return ::GetMenuState(_menu, id, flags); }
|
||||
#endif
|
||||
|
||||
@@ -16,8 +16,8 @@ bool MyGetTimeFormat(LCID locale, DWORD flags, CONST SYSTEMTIME *time,
|
||||
if (numChars == 0)
|
||||
return false;
|
||||
numChars = ::GetTimeFormat(locale, flags, time, format,
|
||||
resultString.GetBuffer(numChars), numChars + 1);
|
||||
resultString.ReleaseBuffer();
|
||||
resultString.GetBuf(numChars), numChars + 1);
|
||||
resultString.ReleaseBuf_CalcLen(numChars);
|
||||
return (numChars != 0);
|
||||
}
|
||||
|
||||
@@ -29,8 +29,8 @@ bool MyGetDateFormat(LCID locale, DWORD flags, CONST SYSTEMTIME *time,
|
||||
if (numChars == 0)
|
||||
return false;
|
||||
numChars = ::GetDateFormat(locale, flags, time, format,
|
||||
resultString.GetBuffer(numChars), numChars + 1);
|
||||
resultString.ReleaseBuffer();
|
||||
resultString.GetBuf(numChars), numChars + 1);
|
||||
resultString.ReleaseBuf_CalcLen(numChars);
|
||||
return (numChars != 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -65,9 +65,9 @@ public:
|
||||
{ return ::GetModuleBaseName(_handle, hModule, baseName, size); }
|
||||
bool MyGetModuleBaseName(HMODULE hModule, CSysString &name)
|
||||
{
|
||||
const int length = 1000;
|
||||
DWORD resultLen = MyGetModuleBaseName(hModule, name.GetBuffer(length), length);
|
||||
name.ReleaseBuffer();
|
||||
const unsigned len = MAX_PATH + 100;
|
||||
DWORD resultLen = MyGetModuleBaseName(hModule, name.GetBuf(len), len);
|
||||
name.ReleaseBuf_CalcLen(len);
|
||||
return (resultLen != 0);
|
||||
}
|
||||
|
||||
@@ -75,9 +75,9 @@ public:
|
||||
{ return ::GetModuleFileNameEx(_handle, hModule, baseName, size); }
|
||||
bool MyGetModuleFileNameEx(HMODULE hModule, CSysString &name)
|
||||
{
|
||||
const int length = MAX_PATH + 100;
|
||||
DWORD resultLen = MyGetModuleFileNameEx(hModule, name.GetBuffer(length), length);
|
||||
name.ReleaseBuffer();
|
||||
const unsigned len = MAX_PATH + 100;
|
||||
DWORD resultLen = MyGetModuleFileNameEx(hModule, name.GetBuf(len), len);
|
||||
name.ReleaseBuf_CalcLen(len);
|
||||
return (resultLen != 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ HRESULT PropVarEm_Set_Str(PROPVARIANT *p, const char *s) throw()
|
||||
p->vt = VT_BSTR;
|
||||
BSTR dest = p->bstrVal;
|
||||
for (UINT i = 0; i <= len; i++)
|
||||
dest[i] = s[i];
|
||||
dest[i] = (Byte)s[i];
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -97,6 +97,48 @@ CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc)
|
||||
return *this;
|
||||
}
|
||||
|
||||
CPropVariant& CPropVariant::operator=(const UString &s)
|
||||
{
|
||||
InternalClear();
|
||||
vt = VT_BSTR;
|
||||
wReserved1 = 0;
|
||||
bstrVal = ::SysAllocStringLen(s, s.Len());
|
||||
if (!bstrVal)
|
||||
throw kMemException;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CPropVariant& CPropVariant::operator=(const UString2 &s)
|
||||
{
|
||||
/*
|
||||
if (s.IsEmpty())
|
||||
*this = L"";
|
||||
else
|
||||
*/
|
||||
{
|
||||
InternalClear();
|
||||
vt = VT_BSTR;
|
||||
wReserved1 = 0;
|
||||
bstrVal = ::SysAllocStringLen(s.GetRawPtr(), s.Len());
|
||||
if (!bstrVal)
|
||||
throw kMemException;
|
||||
/* SysAllocStringLen probably appends a null-terminating character for NULL string.
|
||||
But it doesn't specified in MSDN.
|
||||
But we suppose that it works
|
||||
|
||||
if (!s.GetRawPtr())
|
||||
{
|
||||
*bstrVal = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
/* MSDN: Windows CE: SysAllocStringLen() : Passing invalid (and under some circumstances NULL)
|
||||
pointers to this function causes an unexpected termination of the application.
|
||||
Is it safe? Maybe we must chamnge the code for that case ? */
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
CPropVariant& CPropVariant::operator=(const char *s)
|
||||
{
|
||||
InternalClear();
|
||||
@@ -112,8 +154,9 @@ CPropVariant& CPropVariant::operator=(const char *s)
|
||||
}
|
||||
else
|
||||
{
|
||||
BSTR dest = bstrVal;
|
||||
for (UINT i = 0; i <= len; i++)
|
||||
bstrVal[i] = s[i];
|
||||
dest[i] = (Byte)s[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "../Common/MyTypes.h"
|
||||
#include "../Common/MyWindows.h"
|
||||
#include "../Common/MyString.h"
|
||||
|
||||
namespace NWindows {
|
||||
namespace NCOM {
|
||||
@@ -57,7 +58,7 @@ public:
|
||||
CPropVariant(const CPropVariant &varSrc);
|
||||
CPropVariant(BSTR bstrSrc);
|
||||
CPropVariant(LPCOLESTR lpszSrc);
|
||||
CPropVariant(bool bSrc) { vt = VT_BOOL; wReserved1 = 0; boolVal = (bSrc ? VARIANT_TRUE : VARIANT_FALSE); };
|
||||
CPropVariant(bool bSrc) { vt = VT_BOOL; wReserved1 = 0; boolVal = (bSrc ? VARIANT_TRUE : VARIANT_FALSE); }
|
||||
CPropVariant(Byte value) { vt = VT_UI1; wReserved1 = 0; bVal = value; }
|
||||
|
||||
private:
|
||||
@@ -74,6 +75,8 @@ public:
|
||||
CPropVariant& operator=(const PROPVARIANT &varSrc);
|
||||
CPropVariant& operator=(BSTR bstrSrc);
|
||||
CPropVariant& operator=(LPCOLESTR lpszSrc);
|
||||
CPropVariant& operator=(const UString &s);
|
||||
CPropVariant& operator=(const UString2 &s);
|
||||
CPropVariant& operator=(const char *s);
|
||||
|
||||
CPropVariant& operator=(bool bSrc) throw();
|
||||
|
||||
@@ -93,7 +93,7 @@ void ConvertPropVariantToShortString(const PROPVARIANT &prop, wchar_t *dest) thr
|
||||
case VT_I2: ConvertInt64ToString(prop.iVal, dest); return;
|
||||
case VT_I4: ConvertInt64ToString(prop.lVal, dest); return;
|
||||
case VT_I8: ConvertInt64ToString(prop.hVal.QuadPart, dest); return;
|
||||
case VT_BOOL: dest[0] = VARIANT_BOOLToBool(prop.boolVal) ? '+' : '-'; dest[1] = 0; return;
|
||||
case VT_BOOL: dest[0] = VARIANT_BOOLToBool(prop.boolVal) ? (wchar_t)'+' : (wchar_t)'-'; dest[1] = 0; return;
|
||||
default: dest[0] = '?'; dest[1] = ':'; ConvertUInt32ToString(prop.vt, dest + 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,20 +37,20 @@ void PairToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 value, NCOM:
|
||||
}
|
||||
|
||||
|
||||
AString TypeToString(const char *table[], unsigned num, UInt32 value)
|
||||
AString TypeToString(const char * const table[], unsigned num, UInt32 value)
|
||||
{
|
||||
if (value < num)
|
||||
return table[value];
|
||||
return GetHex(value);
|
||||
}
|
||||
|
||||
void TypeToProp(const char *table[], unsigned num, UInt32 value, NCOM::CPropVariant &prop)
|
||||
void TypeToProp(const char * const table[], unsigned num, UInt32 value, NCOM::CPropVariant &prop)
|
||||
{
|
||||
prop = TypeToString(table, num, value);
|
||||
}
|
||||
|
||||
|
||||
AString FlagsToString(const char **names, unsigned num, UInt32 flags)
|
||||
AString FlagsToString(const char * const *names, unsigned num, UInt32 flags)
|
||||
{
|
||||
AString s;
|
||||
for (unsigned i = 0; i < num; i++)
|
||||
|
||||
@@ -16,12 +16,12 @@ struct CUInt32PCharPair
|
||||
AString TypePairToString(const CUInt32PCharPair *pairs, unsigned num, UInt32 value);
|
||||
void PairToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 value, NWindows::NCOM::CPropVariant &prop);
|
||||
|
||||
AString FlagsToString(const char **names, unsigned num, UInt32 flags);
|
||||
AString FlagsToString(const char * const *names, unsigned num, UInt32 flags);
|
||||
AString FlagsToString(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags);
|
||||
void FlagsToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags, NWindows::NCOM::CPropVariant &prop);
|
||||
|
||||
AString TypeToString(const char *table[], unsigned num, UInt32 value);
|
||||
void TypeToProp(const char *table[], unsigned num, UInt32 value, NWindows::NCOM::CPropVariant &prop);
|
||||
AString TypeToString(const char * const table[], unsigned num, UInt32 value);
|
||||
void TypeToProp(const char * const table[], unsigned num, UInt32 value, NWindows::NCOM::CPropVariant &prop);
|
||||
|
||||
#define PAIR_TO_PROP(pairs, value, prop) PairToProp(pairs, ARRAY_SIZE(pairs), value, prop)
|
||||
#define FLAGS_TO_PROP(pairs, value, prop) FlagsToProp(pairs, ARRAY_SIZE(pairs), value, prop)
|
||||
|
||||
+56
-34
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
#ifndef _UNICODE
|
||||
#include "../Common/StringConvert.h"
|
||||
#endif
|
||||
@@ -75,15 +77,15 @@ LONG CKey::RecurseDeleteKey(LPCTSTR subKeyName) throw()
|
||||
if (res != ERROR_SUCCESS)
|
||||
return res;
|
||||
FILETIME fileTime;
|
||||
const UInt32 kBufferSize = MAX_PATH + 1; // 256 in ATL
|
||||
DWORD size = kBufferSize;
|
||||
TCHAR buffer[kBufferSize];
|
||||
const UInt32 kBufSize = MAX_PATH + 1; // 256 in ATL
|
||||
DWORD size = kBufSize;
|
||||
TCHAR buffer[kBufSize];
|
||||
while (RegEnumKeyEx(key._object, 0, buffer, &size, NULL, NULL, NULL, &fileTime) == ERROR_SUCCESS)
|
||||
{
|
||||
res = key.RecurseDeleteKey(buffer);
|
||||
if (res != ERROR_SUCCESS)
|
||||
return res;
|
||||
size = kBufferSize;
|
||||
size = kBufSize;
|
||||
}
|
||||
key.Close();
|
||||
return DeleteSubKey(subKeyName);
|
||||
@@ -226,7 +228,6 @@ LONG CKey::GetValue_IfOk(LPCTSTR name, bool &value) throw()
|
||||
|
||||
LONG CKey::QueryValue(LPCTSTR name, LPTSTR value, UInt32 &count) throw()
|
||||
{
|
||||
MYASSERT(count != NULL);
|
||||
DWORD type = 0;
|
||||
LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, (LPBYTE)value, (DWORD *)&count);
|
||||
MYASSERT((res != ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ));
|
||||
@@ -237,38 +238,47 @@ LONG CKey::QueryValue(LPCTSTR name, CSysString &value)
|
||||
{
|
||||
value.Empty();
|
||||
DWORD type = 0;
|
||||
UInt32 currentSize = 0;
|
||||
LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, NULL, (DWORD *)¤tSize);
|
||||
UInt32 curSize = 0;
|
||||
LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, NULL, (DWORD *)&curSize);
|
||||
if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)
|
||||
return res;
|
||||
res = QueryValue(name, value.GetBuffer(currentSize), currentSize);
|
||||
value.ReleaseBuffer();
|
||||
UInt32 curSize2 = curSize;
|
||||
res = QueryValue(name, value.GetBuf(curSize), curSize2);
|
||||
if (curSize > curSize2)
|
||||
curSize = curSize2;
|
||||
value.ReleaseBuf_CalcLen(curSize / sizeof(TCHAR));
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
#ifndef _UNICODE
|
||||
|
||||
LONG CKey::QueryValue(LPCWSTR name, LPWSTR value, UInt32 &count)
|
||||
{
|
||||
MYASSERT(count != NULL);
|
||||
DWORD type = 0;
|
||||
LONG res = RegQueryValueExW(_object, name, NULL, &type, (LPBYTE)value, (DWORD *)&count);
|
||||
MYASSERT((res != ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ));
|
||||
return res;
|
||||
}
|
||||
|
||||
LONG CKey::QueryValue(LPCWSTR name, UString &value)
|
||||
{
|
||||
value.Empty();
|
||||
DWORD type = 0;
|
||||
UInt32 currentSize = 0;
|
||||
UInt32 curSize = 0;
|
||||
|
||||
LONG res;
|
||||
|
||||
if (g_IsNT)
|
||||
{
|
||||
res = RegQueryValueExW(_object, name, NULL, &type, NULL, (DWORD *)¤tSize);
|
||||
res = RegQueryValueExW(_object, name, NULL, &type, NULL, (DWORD *)&curSize);
|
||||
if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)
|
||||
return res;
|
||||
res = QueryValue(name, value.GetBuffer(currentSize), currentSize);
|
||||
value.ReleaseBuffer();
|
||||
UInt32 curSize2 = curSize;
|
||||
res = QueryValue(name, value.GetBuf(curSize), curSize2);
|
||||
if (curSize > curSize2)
|
||||
curSize = curSize2;
|
||||
value.ReleaseBuf_CalcLen(curSize / sizeof(wchar_t));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -276,10 +286,13 @@ LONG CKey::QueryValue(LPCWSTR name, UString &value)
|
||||
res = QueryValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name), vTemp);
|
||||
value = GetUnicodeString(vTemp);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
LONG CKey::QueryValue(LPCTSTR name, void *value, UInt32 &count) throw()
|
||||
{
|
||||
DWORD type = 0;
|
||||
@@ -304,14 +317,14 @@ LONG CKey::EnumKeys(CSysStringVector &keyNames)
|
||||
{
|
||||
keyNames.Clear();
|
||||
CSysString keyName;
|
||||
for (UInt32 index = 0; ; index++)
|
||||
for (DWORD index = 0; ; index++)
|
||||
{
|
||||
const UInt32 kBufferSize = MAX_PATH + 1; // 256 in ATL
|
||||
const unsigned kBufSize = MAX_PATH + 1; // 256 in ATL
|
||||
FILETIME lastWriteTime;
|
||||
UInt32 nameSize = kBufferSize;
|
||||
LONG result = ::RegEnumKeyEx(_object, index, keyName.GetBuffer(kBufferSize),
|
||||
UInt32 nameSize = kBufSize;
|
||||
LONG result = ::RegEnumKeyEx(_object, index, keyName.GetBuf(kBufSize),
|
||||
(DWORD *)&nameSize, NULL, NULL, NULL, &lastWriteTime);
|
||||
keyName.ReleaseBuffer();
|
||||
keyName.ReleaseBuf_CalcLen(kBufSize);
|
||||
if (result == ERROR_NO_MORE_ITEMS)
|
||||
break;
|
||||
if (result != ERROR_SUCCESS)
|
||||
@@ -321,47 +334,56 @@ LONG CKey::EnumKeys(CSysStringVector &keyNames)
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
LONG CKey::SetValue_Strings(LPCTSTR valueName, const UStringVector &strings) throw()
|
||||
LONG CKey::SetValue_Strings(LPCTSTR valueName, const UStringVector &strings)
|
||||
{
|
||||
UInt32 numChars = 0;
|
||||
size_t numChars = 0;
|
||||
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < strings.Size(); i++)
|
||||
numChars += strings[i].Len() + 1;
|
||||
CBuffer<wchar_t> buffer(numChars);
|
||||
unsigned pos = 0;
|
||||
|
||||
CObjArray<wchar_t> buffer(numChars);
|
||||
size_t pos = 0;
|
||||
|
||||
for (i = 0; i < strings.Size(); i++)
|
||||
{
|
||||
const UString &s = strings[i];
|
||||
MyStringCopy((wchar_t *)buffer + pos, (const wchar_t *)s);
|
||||
pos += s.Len() + 1;
|
||||
size_t size = s.Len() + 1;
|
||||
wmemcpy(buffer + pos, s, size);
|
||||
pos += size;
|
||||
}
|
||||
return SetValue(valueName, buffer, numChars * sizeof(wchar_t));
|
||||
return SetValue(valueName, buffer, (UInt32)numChars * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
LONG CKey::GetValue_Strings(LPCTSTR valueName, UStringVector &strings)
|
||||
{
|
||||
strings.Clear();
|
||||
CByteBuffer buffer;
|
||||
UInt32 dataSize;
|
||||
UInt32 dataSize = 0;
|
||||
LONG res = QueryValue(valueName, buffer, dataSize);
|
||||
if (res != ERROR_SUCCESS)
|
||||
return res;
|
||||
if (dataSize > buffer.Size())
|
||||
return E_FAIL;
|
||||
if (dataSize % sizeof(wchar_t) != 0)
|
||||
return E_FAIL;
|
||||
|
||||
const wchar_t *data = (const wchar_t *)(const Byte *)buffer;
|
||||
unsigned numChars = dataSize / sizeof(wchar_t);
|
||||
size_t numChars = dataSize / sizeof(wchar_t);
|
||||
size_t prev = 0;
|
||||
UString s;
|
||||
for (unsigned i = 0; i < numChars; i++)
|
||||
|
||||
for (size_t i = 0; i < numChars; i++)
|
||||
{
|
||||
wchar_t c = data[i];
|
||||
if (c == 0)
|
||||
if (data[i] == 0)
|
||||
{
|
||||
s = data + prev;
|
||||
strings.Add(s);
|
||||
s.Empty();
|
||||
prev = i + 1;
|
||||
}
|
||||
else
|
||||
s += c;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
|
||||
LONG SetValue(LPCTSTR name, const void *value, UInt32 size) throw();
|
||||
|
||||
LONG SetValue_Strings(LPCTSTR valueName, const UStringVector &strings) throw();
|
||||
LONG SetValue_Strings(LPCTSTR valueName, const UStringVector &strings);
|
||||
LONG GetValue_Strings(LPCTSTR valueName, UStringVector &strings);
|
||||
|
||||
LONG SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) throw();
|
||||
|
||||
@@ -25,10 +25,10 @@ static CSysString MyLoadStringA(HINSTANCE hInstance, UINT resourceID)
|
||||
do
|
||||
{
|
||||
size <<= 1;
|
||||
len = ::LoadString(hInstance, resourceID, s.GetBuffer(size - 1), size);
|
||||
len = ::LoadString(hInstance, resourceID, s.GetBuf(size - 1), size);
|
||||
}
|
||||
while (size - len <= 1);
|
||||
s.ReleaseBuffer();
|
||||
s.ReleaseBuf_CalcLen(len);
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -43,10 +43,10 @@ static void MyLoadString2(HINSTANCE hInstance, UINT resourceID, UString &s)
|
||||
do
|
||||
{
|
||||
size <<= 1;
|
||||
len = ::LoadStringW(hInstance, resourceID, s.GetBuffer(size - 1), size);
|
||||
len = ::LoadStringW(hInstance, resourceID, s.GetBuf(size - 1), size);
|
||||
}
|
||||
while (size - len <= 1);
|
||||
s.ReleaseBuffer();
|
||||
s.ReleaseBuf_CalcLen(len);
|
||||
}
|
||||
|
||||
// NT4 doesn't support LoadStringW(,,, 0) to get pointer to resource string. So we don't use it.
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../Common/MyString.h"
|
||||
|
||||
#include "SecurityUtils.h"
|
||||
|
||||
namespace NWindows {
|
||||
@@ -14,17 +16,18 @@ bool MyLookupAccountSid(LPCTSTR systemName, PSID sid,
|
||||
DWORD accountNameSize = 0, domainNameSize = 0;
|
||||
|
||||
if (!::LookupAccountSid(systemName, sid,
|
||||
accountName.GetBuffer(0), &accountNameSize,
|
||||
domainName.GetBuffer(0), &domainNameSize, sidNameUse))
|
||||
accountName.GetBuf(0), &accountNameSize,
|
||||
domainName.GetBuf(0), &domainNameSize, sidNameUse))
|
||||
{
|
||||
if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
||||
return false;
|
||||
}
|
||||
DWORD accountNameSize2 = accountNameSize, domainNameSize2 = domainNameSize;
|
||||
bool result = BOOLToBool(::LookupAccountSid(systemName, sid,
|
||||
accountName.GetBuffer(accountNameSize), &accountNameSize,
|
||||
domainName.GetBuffer(domainNameSize), &domainNameSize, sidNameUse));
|
||||
accountName.ReleaseBuffer();
|
||||
domainName.ReleaseBuffer();
|
||||
accountName.GetBuf(accountNameSize), &accountNameSize2,
|
||||
domainName.GetBuf(domainNameSize), &domainNameSize2, sidNameUse));
|
||||
accountName.ReleaseBuf_CalcLen(accountNameSize);
|
||||
domainName.ReleaseBuf_CalcLen(domainNameSize);
|
||||
return result;
|
||||
}
|
||||
*/
|
||||
|
||||
+19
-13
@@ -95,16 +95,18 @@ UString CDrop::QueryFileName(UINT fileIndex)
|
||||
{
|
||||
AString fileNameA;
|
||||
UINT bufferSize = QueryFile(fileIndex, (LPTSTR)NULL, 0);
|
||||
QueryFile(fileIndex, fileNameA.GetBuffer(bufferSize + 2), bufferSize + 1);
|
||||
fileNameA.ReleaseBuffer();
|
||||
const unsigned len = bufferSize + 2;
|
||||
QueryFile(fileIndex, fileNameA.GetBuf(len), bufferSize + 1);
|
||||
fileNameA.ReleaseBuf_CalcLen(len);
|
||||
fileName = GetUnicodeString(fileNameA);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
UINT bufferSize = QueryFile(fileIndex, (LPWSTR)NULL, 0);
|
||||
QueryFile(fileIndex, fileName.GetBuffer(bufferSize + 2), bufferSize + 1);
|
||||
fileName.ReleaseBuffer();
|
||||
const unsigned len = bufferSize + 2;
|
||||
QueryFile(fileIndex, fileName.GetBuf(len), bufferSize + 1);
|
||||
fileName.ReleaseBuf_CalcLen(len);
|
||||
}
|
||||
return fileName;
|
||||
}
|
||||
@@ -120,8 +122,9 @@ void CDrop::QueryFileNames(UStringVector &fileNames)
|
||||
|
||||
bool GetPathFromIDList(LPCITEMIDLIST itemIDList, CSysString &path)
|
||||
{
|
||||
bool result = BOOLToBool(::SHGetPathFromIDList(itemIDList, path.GetBuffer(MAX_PATH * 2)));
|
||||
path.ReleaseBuffer();
|
||||
const unsigned len = MAX_PATH * 2;
|
||||
bool result = BOOLToBool(::SHGetPathFromIDList(itemIDList, path.GetBuf(len)));
|
||||
path.ReleaseBuf_CalcLen(len);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -208,14 +211,16 @@ bool BrowseForFolder(HWND owner, LPCTSTR title, UINT ulFlags,
|
||||
browseInfo.hwndOwner = owner;
|
||||
browseInfo.pidlRoot = NULL;
|
||||
|
||||
// there are Unicode/astring problems in WinCE SDK!!!
|
||||
// there are Unicode/Astring problems in some WinCE SDK ?
|
||||
/*
|
||||
#ifdef UNDER_CE
|
||||
browseInfo.pszDisplayName = (LPSTR)displayName.GetBuffer(MAX_PATH);
|
||||
browseInfo.pszDisplayName = (LPSTR)displayName.GetBuf(MAX_PATH);
|
||||
browseInfo.lpszTitle = (LPCSTR)title;
|
||||
#else
|
||||
browseInfo.pszDisplayName = displayName.GetBuffer(MAX_PATH);
|
||||
*/
|
||||
browseInfo.pszDisplayName = displayName.GetBuf(MAX_PATH);
|
||||
browseInfo.lpszTitle = title;
|
||||
#endif
|
||||
// #endif
|
||||
browseInfo.ulFlags = ulFlags;
|
||||
browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc : NULL;
|
||||
browseInfo.lParam = (LPARAM)initialFolder;
|
||||
@@ -244,8 +249,9 @@ bool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path)
|
||||
::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHGetPathFromIDListW");
|
||||
if (shGetPathFromIDListW == 0)
|
||||
return false;
|
||||
bool result = BOOLToBool(shGetPathFromIDListW(itemIDList, path.GetBuffer(MAX_PATH * 2)));
|
||||
path.ReleaseBuffer();
|
||||
const unsigned len = MAX_PATH * 2;
|
||||
bool result = BOOLToBool(shGetPathFromIDListW(itemIDList, path.GetBuf(len)));
|
||||
path.ReleaseBuf_CalcLen(len);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -302,7 +308,7 @@ static bool BrowseForFolder(HWND owner, LPCWSTR title, UINT ulFlags,
|
||||
BROWSEINFOW browseInfo;
|
||||
browseInfo.hwndOwner = owner;
|
||||
browseInfo.pidlRoot = NULL;
|
||||
browseInfo.pszDisplayName = displayName.GetBuffer(MAX_PATH);
|
||||
browseInfo.pszDisplayName = displayName.GetBuf(MAX_PATH);
|
||||
browseInfo.lpszTitle = title;
|
||||
browseInfo.ulFlags = ulFlags;
|
||||
browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc2 : NULL;
|
||||
|
||||
+22
-12
@@ -114,13 +114,18 @@ bool MySetWindowText(HWND wnd, LPCWSTR s)
|
||||
bool CWindow::GetText(CSysString &s)
|
||||
{
|
||||
s.Empty();
|
||||
int length = GetTextLength();
|
||||
if (length == 0)
|
||||
int len = GetTextLength();
|
||||
if (len == 0)
|
||||
return (::GetLastError() == ERROR_SUCCESS);
|
||||
TCHAR *p = s.GetBuf(len);
|
||||
{
|
||||
int len2 = GetText(p, len + 1);
|
||||
if (len > len2)
|
||||
len = len2;
|
||||
}
|
||||
s.ReleaseBuf_CalcLen(len);
|
||||
if (len == 0)
|
||||
return (::GetLastError() == ERROR_SUCCESS);
|
||||
length = GetText(s.GetBuffer(length), length + 1);
|
||||
s.ReleaseBuffer();
|
||||
if (length == 0)
|
||||
return (::GetLastError() != ERROR_SUCCESS);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -130,18 +135,23 @@ bool CWindow::GetText(UString &s)
|
||||
if (g_IsNT)
|
||||
{
|
||||
s.Empty();
|
||||
int length = GetWindowTextLengthW(_window);
|
||||
if (length == 0)
|
||||
int len = GetWindowTextLengthW(_window);
|
||||
if (len == 0)
|
||||
return (::GetLastError() == ERROR_SUCCESS);
|
||||
length = GetWindowTextW(_window, s.GetBuffer(length), length + 1);
|
||||
s.ReleaseBuffer();
|
||||
if (length == 0)
|
||||
wchar_t *p = s.GetBuf(len);
|
||||
{
|
||||
int len2 = GetWindowTextW(_window, p, len + 1);
|
||||
if (len > len2)
|
||||
len = len2;
|
||||
}
|
||||
s.ReleaseBuf_CalcLen(len);
|
||||
if (len == 0)
|
||||
return (::GetLastError() == ERROR_SUCCESS);
|
||||
return true;
|
||||
}
|
||||
CSysString sysString;
|
||||
bool result = GetText(sysString);
|
||||
s = GetUnicodeString(sysString);
|
||||
MultiByteToUnicodeString2(s, sysString);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user