Mo stuff
This commit is contained in:
@@ -33,7 +33,7 @@ private:
|
|||||||
static FilePath _cacheLocation;
|
static FilePath _cacheLocation;
|
||||||
static std::unordered_map<ULONG64, OpenFileInfo> _openFileMap;
|
static std::unordered_map<ULONG64, OpenFileInfo> _openFileMap;
|
||||||
static std::unique_ptr<std::thread> _fileListThread;
|
static std::unique_ptr<std::thread> _fileListThread;
|
||||||
static bool _fileListStopRequested;
|
static HANDLE _fileListStopEvent;
|
||||||
static CSiaFileTreePtr _siaFileTree;
|
static CSiaFileTreePtr _siaFileTree;
|
||||||
static std::mutex _fileTreeMutex;
|
static std::mutex _fileTreeMutex;
|
||||||
static std::unique_ptr<std::thread> _mountThread;
|
static std::unique_ptr<std::thread> _mountThread;
|
||||||
@@ -48,12 +48,11 @@ private:
|
|||||||
|
|
||||||
static bool AddFileToCache(const SString& siaPath, const SString& cacheLocation)
|
static bool AddFileToCache(const SString& siaPath, const SString& cacheLocation)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
|
||||||
FilePath tempFilePath = FilePath::GetTempDirectory();
|
FilePath tempFilePath = FilePath::GetTempDirectory();
|
||||||
tempFilePath.Append(GenerateSha256(siaPath) + ".siatmp");
|
tempFilePath.Append(GenerateSha256(siaPath) + ".siatmp");
|
||||||
|
|
||||||
// TODO Check cache size is large enough to hold new file
|
// TODO Check cache size is large enough to hold new file
|
||||||
ret = ApiSuccess(_siaApi->GetRenter()->DownloadFile(siaPath, tempFilePath));
|
bool ret = ApiSuccess(_siaApi->GetRenter()->DownloadFile(siaPath, tempFilePath));
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
FilePath src(tempFilePath);
|
FilePath src(tempFilePath);
|
||||||
@@ -106,10 +105,10 @@ private:
|
|||||||
{
|
{
|
||||||
if (!_fileListThread)
|
if (!_fileListThread)
|
||||||
{
|
{
|
||||||
_fileListStopRequested = false;
|
_fileListStopEvent = ::CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||||
_fileListThread.reset(new std::thread([]()
|
_fileListThread.reset(new std::thread([]()
|
||||||
{
|
{
|
||||||
while (!_fileListStopRequested)
|
do
|
||||||
{
|
{
|
||||||
CSiaFileTreePtr siaFileTree;
|
CSiaFileTreePtr siaFileTree;
|
||||||
_siaApi->GetRenter()->GetFileTree(siaFileTree);
|
_siaApi->GetRenter()->GetFileTree(siaFileTree);
|
||||||
@@ -117,13 +116,7 @@ private:
|
|||||||
std::lock_guard<std::mutex> l(_fileTreeMutex);
|
std::lock_guard<std::mutex> l(_fileTreeMutex);
|
||||||
_siaFileTree = siaFileTree;
|
_siaFileTree = siaFileTree;
|
||||||
}
|
}
|
||||||
|
} while (::WaitForSingleObject(_fileListStopEvent, 1000) == WAIT_TIMEOUT);
|
||||||
if (!_fileListStopRequested)
|
|
||||||
{
|
|
||||||
// TODO Change to WaitForSingleObject() for immediate termination
|
|
||||||
Sleep(1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -132,63 +125,64 @@ private:
|
|||||||
{
|
{
|
||||||
if (_fileListThread)
|
if (_fileListThread)
|
||||||
{
|
{
|
||||||
_fileListStopRequested = true;
|
::SetEvent(_fileListStopEvent);
|
||||||
_fileListThread->join();
|
_fileListThread->join();
|
||||||
_fileListThread.reset(nullptr);
|
_fileListThread.reset(nullptr);
|
||||||
|
::CloseHandle(_fileListStopEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dokan callbacks
|
// Dokan callbacks
|
||||||
private:
|
private:
|
||||||
static NTSTATUS DOKAN_CALLBACK Sia_ZwCreateFile(
|
static NTSTATUS DOKAN_CALLBACK Sia_ZwCreateFile(
|
||||||
LPCWSTR FileName,
|
LPCWSTR fileName,
|
||||||
PDOKAN_IO_SECURITY_CONTEXT SecurityContext,
|
PDOKAN_IO_SECURITY_CONTEXT securityContext,
|
||||||
ACCESS_MASK DesiredAccess,
|
ACCESS_MASK desiredAccess,
|
||||||
ULONG FileAttributes,
|
ULONG fileAttributes,
|
||||||
ULONG ShareAccess,
|
ULONG shareAccess,
|
||||||
ULONG CreateDisposition,
|
ULONG createDisposition,
|
||||||
ULONG CreateOptions,
|
ULONG createOptions,
|
||||||
PDOKAN_FILE_INFO DokanFileInfo)
|
PDOKAN_FILE_INFO dokanFileInfo)
|
||||||
{
|
{
|
||||||
SECURITY_ATTRIBUTES securityAttrib;
|
SECURITY_ATTRIBUTES securityAttrib;
|
||||||
securityAttrib.nLength = sizeof(securityAttrib);
|
securityAttrib.nLength = sizeof(securityAttrib);
|
||||||
securityAttrib.lpSecurityDescriptor = SecurityContext->AccessState.SecurityDescriptor;
|
securityAttrib.lpSecurityDescriptor = securityContext->AccessState.SecurityDescriptor;
|
||||||
securityAttrib.bInheritHandle = FALSE;
|
securityAttrib.bInheritHandle = FALSE;
|
||||||
|
|
||||||
DWORD fileAttributesAndFlags;
|
DWORD fileAttributesAndFlags;
|
||||||
DWORD creationDisposition;
|
DWORD creationDisposition;
|
||||||
DokanMapKernelToUserCreateFileFlags(FileAttributes, CreateOptions, CreateDisposition, &fileAttributesAndFlags, &creationDisposition);
|
DokanMapKernelToUserCreateFileFlags(fileAttributes, createOptions, createDisposition, &fileAttributesAndFlags, &creationDisposition);
|
||||||
|
|
||||||
ACCESS_MASK genericDesiredAccess = DokanMapStandardToGenericAccess(DesiredAccess);
|
ACCESS_MASK genericDesiredAccess = DokanMapStandardToGenericAccess(desiredAccess);
|
||||||
|
|
||||||
NTSTATUS ret = STATUS_SUCCESS;
|
NTSTATUS ret = STATUS_SUCCESS;
|
||||||
// Probably not going to happen, but just in case
|
// Probably not going to happen, but just in case
|
||||||
if (FilePath(FileName).IsUNC())
|
if (FilePath(fileName).IsUNC())
|
||||||
{
|
{
|
||||||
ret = STATUS_ILLEGAL_ELEMENT_ADDRESS;
|
ret = STATUS_ILLEGAL_ELEMENT_ADDRESS;
|
||||||
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DokanCreateFile(FileName, fileAttributesAndFlags, creationDisposition, genericDesiredAccess, ret)));
|
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DokanCreateFile(fileName, fileAttributesAndFlags, creationDisposition, genericDesiredAccess, ret)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// When filePath is a directory, needs to change the flag so that the file can
|
// When filePath is a directory, needs to change the flag so that the file can
|
||||||
// be opened.
|
// be opened.
|
||||||
FilePath cacheFilePath(GetCacheLocation(), &FileName[1]);
|
FilePath cacheFilePath(GetCacheLocation(), &fileName[1]);
|
||||||
DWORD fileAttr = ::GetFileAttributes(&cacheFilePath[0]);
|
DWORD fileAttr = ::GetFileAttributes(&cacheFilePath[0]);
|
||||||
|
|
||||||
if ((fileAttr != INVALID_FILE_ATTRIBUTES) &&
|
if ((fileAttr != INVALID_FILE_ATTRIBUTES) &&
|
||||||
(fileAttr & FILE_ATTRIBUTE_DIRECTORY) &&
|
(fileAttr & FILE_ATTRIBUTE_DIRECTORY) &&
|
||||||
!(CreateOptions & FILE_NON_DIRECTORY_FILE))
|
!(createOptions & FILE_NON_DIRECTORY_FILE))
|
||||||
{
|
{
|
||||||
DokanFileInfo->IsDirectory = TRUE;
|
dokanFileInfo->IsDirectory = TRUE;
|
||||||
if (DesiredAccess & DELETE)
|
if (desiredAccess & DELETE)
|
||||||
{
|
{
|
||||||
// Needed by FindFirstFile to see if directory is empty or not
|
// Needed by FindFirstFile to see if directory is empty or not
|
||||||
ShareAccess |= FILE_SHARE_READ;
|
shareAccess |= FILE_SHARE_READ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Folder (cache operation only)
|
// Folder (cache operation only)
|
||||||
if (DokanFileInfo->IsDirectory)
|
if (dokanFileInfo->IsDirectory)
|
||||||
{
|
{
|
||||||
if (creationDisposition == CREATE_NEW)
|
if (creationDisposition == CREATE_NEW)
|
||||||
{
|
{
|
||||||
@@ -215,13 +209,13 @@ private:
|
|||||||
//Check first if we're trying to open a file as a directory.
|
//Check first if we're trying to open a file as a directory.
|
||||||
if (fileAttr != INVALID_FILE_ATTRIBUTES &&
|
if (fileAttr != INVALID_FILE_ATTRIBUTES &&
|
||||||
!(fileAttr & FILE_ATTRIBUTE_DIRECTORY) &&
|
!(fileAttr & FILE_ATTRIBUTE_DIRECTORY) &&
|
||||||
(CreateOptions & FILE_DIRECTORY_FILE))
|
(createOptions & FILE_DIRECTORY_FILE))
|
||||||
{
|
{
|
||||||
return STATUS_NOT_A_DIRECTORY;
|
return STATUS_NOT_A_DIRECTORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FILE_FLAG_BACKUP_SEMANTICS is required for opening directory handles
|
// FILE_FLAG_BACKUP_SEMANTICS is required for opening directory handles
|
||||||
HANDLE handle = ::CreateFile(&cacheFilePath[0], genericDesiredAccess, ShareAccess, &securityAttrib, OPEN_EXISTING, fileAttributesAndFlags | FILE_FLAG_BACKUP_SEMANTICS, nullptr);
|
HANDLE handle = ::CreateFile(&cacheFilePath[0], genericDesiredAccess, shareAccess, &securityAttrib, OPEN_EXISTING, fileAttributesAndFlags | FILE_FLAG_BACKUP_SEMANTICS, nullptr);
|
||||||
if (handle == INVALID_HANDLE_VALUE)
|
if (handle == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
DWORD error = GetLastError();
|
DWORD error = GetLastError();
|
||||||
@@ -229,14 +223,14 @@ private:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DokanFileInfo->Context = reinterpret_cast<ULONG64>(handle); // save the file handle in Context
|
dokanFileInfo->Context = reinterpret_cast<ULONG64>(handle); // save the file handle in Context
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // File (cache and/or Sia operation)
|
else // File (cache and/or Sia operation)
|
||||||
{
|
{
|
||||||
// Formulate Sia path
|
// Formulate Sia path
|
||||||
SString siaPath = CSiaApi::FormatToSiaPath(FilePath(FileName).SkipRoot()); // Strip drive letter to get Sia path
|
SString siaPath = CSiaApi::FormatToSiaPath(FilePath(fileName).SkipRoot()); // Strip drive letter to get Sia path
|
||||||
if (siaPath.Length())
|
if (siaPath.Length())
|
||||||
{
|
{
|
||||||
// If cache file already exists and is a directory, requested file operation isn't valid
|
// If cache file already exists and is a directory, requested file operation isn't valid
|
||||||
@@ -351,7 +345,7 @@ private:
|
|||||||
HANDLE handle = ::CreateFile(
|
HANDLE handle = ::CreateFile(
|
||||||
&cacheFilePath[0],
|
&cacheFilePath[0],
|
||||||
genericDesiredAccess,
|
genericDesiredAccess,
|
||||||
ShareAccess,
|
shareAccess,
|
||||||
&securityAttrib,
|
&securityAttrib,
|
||||||
creationDisposition,
|
creationDisposition,
|
||||||
fileAttributesAndFlags,
|
fileAttributesAndFlags,
|
||||||
@@ -362,7 +356,7 @@ private:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DokanFileInfo->Context = reinterpret_cast<ULONG64>(handle); // save the file handle in Context
|
dokanFileInfo->Context = reinterpret_cast<ULONG64>(handle); // save the file handle in Context
|
||||||
if ((creationDisposition == OPEN_ALWAYS) || (creationDisposition == CREATE_ALWAYS))
|
if ((creationDisposition == OPEN_ALWAYS) || (creationDisposition == CREATE_ALWAYS))
|
||||||
{
|
{
|
||||||
DWORD error = GetLastError();
|
DWORD error = GetLastError();
|
||||||
@@ -376,10 +370,9 @@ private:
|
|||||||
ofi.SiaPath = siaPath;
|
ofi.SiaPath = siaPath;
|
||||||
ofi.CacheFilePath = cacheFilePath;
|
ofi.CacheFilePath = cacheFilePath;
|
||||||
// TODO Detect if file is read-only
|
// TODO Detect if file is read-only
|
||||||
// TODO Quick hash to detect changes
|
|
||||||
ofi.Changed = false;
|
ofi.Changed = false;
|
||||||
std::lock_guard<std::mutex> l(_dokanMutex);
|
std::lock_guard<std::mutex> l(_dokanMutex);
|
||||||
_openFileMap.insert({ DokanFileInfo->Context, ofi });
|
_openFileMap.insert({ dokanFileInfo->Context, ofi });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -403,22 +396,23 @@ private:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS DOKAN_CALLBACK Sia_FindFiles(LPCWSTR FileName, PFillFindData FillFindData, PDOKAN_FILE_INFO DokanFileInfo)
|
static NTSTATUS DOKAN_CALLBACK Sia_FindFiles(LPCWSTR fileName, PFillFindData fillFindData, PDOKAN_FILE_INFO dokanFileInfo)
|
||||||
{
|
{
|
||||||
|
NTSTATUS ret = STATUS_SUCCESS;
|
||||||
auto siaFileTree = _siaFileTree;
|
auto siaFileTree = _siaFileTree;
|
||||||
if (siaFileTree)
|
if (siaFileTree)
|
||||||
{
|
{
|
||||||
SString siaQuery = CSiaApi::FormatToSiaPath(FilePath(FileName).SkipRoot());
|
SString siaQuery = CSiaApi::FormatToSiaPath(FilePath(fileName).SkipRoot());
|
||||||
|
|
||||||
FilePath cachePath = GetCacheLocation();;
|
FilePath cachePath = GetCacheLocation();;
|
||||||
FilePath rootPath = siaQuery;
|
FilePath rootPath = siaQuery;
|
||||||
if (FilePath::DirSep == FileName)
|
if (FilePath::DirSep == fileName)
|
||||||
{
|
{
|
||||||
siaQuery += L"/*.*";
|
siaQuery += L"/*.*";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cachePath.Append(&FileName[1]);
|
cachePath.Append(&fileName[1]);
|
||||||
if (cachePath.IsDirectory())
|
if (cachePath.IsDirectory())
|
||||||
{
|
{
|
||||||
siaQuery += L"/*.*";
|
siaQuery += L"/*.*";
|
||||||
@@ -432,79 +426,120 @@ private:
|
|||||||
|
|
||||||
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DokanFindFiles(cachePath, rootPath, siaQuery)));
|
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DokanFindFiles(cachePath, rootPath, siaQuery)));
|
||||||
|
|
||||||
// TODO Grab live filesystem items
|
WIN32_FIND_DATA findData = { 0 };
|
||||||
|
HANDLE findHandle = ::FindFirstFile(&cachePath[0], &findData);
|
||||||
|
if (findHandle == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
DWORD error = GetLastError();
|
||||||
|
ret = DokanNtStatusFromWin32(error);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Find local files
|
||||||
|
std::vector<SString> dirs;
|
||||||
|
std::vector<SString> files;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if ((wcscmp(findData.cFileName, L".") != 0) && (wcscmp(findData.cFileName, L"..") != 0))
|
||||||
|
{
|
||||||
|
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
|
{
|
||||||
|
dirs.push_back(findData.cFileName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
files.push_back(findData.cFileName);
|
||||||
|
}
|
||||||
|
fillFindData(&findData, dokanFileInfo);
|
||||||
|
}
|
||||||
|
} while (::FindNextFile(findHandle, &findData) != 0);
|
||||||
|
::FindClose(findHandle);
|
||||||
|
|
||||||
auto dirList = siaFileTree->QueryDirectories(rootPath);
|
// Find Sia directories
|
||||||
for (auto& dir : dirList)
|
auto dirList = siaFileTree->QueryDirectories(rootPath);
|
||||||
{
|
for (auto& dir : dirList)
|
||||||
WIN32_FIND_DATA fd = { 0 };
|
{
|
||||||
wcscpy_s(fd.cFileName, dir.str().c_str());
|
if (std::find(dirs.begin(), dirs.end(), dir) == dirs.end())
|
||||||
fd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
|
{
|
||||||
FillFindData(&fd, DokanFileInfo);
|
WIN32_FIND_DATA fd = { 0 };
|
||||||
|
wcscpy_s(fd.cFileName, dir.str().c_str());
|
||||||
// Create cache sub-folder
|
fd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
|
||||||
FilePath subCachePath(cachePath, dir);
|
fillFindData(&fd, dokanFileInfo);
|
||||||
if (!subCachePath.IsDirectory())
|
|
||||||
{
|
|
||||||
subCachePath.CreateDirectory();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto fileList = siaFileTree->Query(siaQuery);
|
// Create cache sub-folder
|
||||||
for (auto& file : fileList)
|
FilePath subCachePath(cachePath, dir);
|
||||||
{
|
if (!subCachePath.IsDirectory())
|
||||||
WIN32_FIND_DATA fd = { 0 };
|
{
|
||||||
wcscpy_s(fd.cFileName, ::PathFindFileName(file->GetSiaPath().str().c_str()));
|
subCachePath.CreateDirectory();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LARGE_INTEGER li = { 0 };
|
// Find Sia files
|
||||||
li.QuadPart = file->GetFileSize();
|
auto fileList = siaFileTree->Query(siaQuery);
|
||||||
fd.nFileSizeHigh = li.HighPart;
|
for (auto& file : fileList)
|
||||||
fd.nFileSizeLow = li.LowPart;
|
{
|
||||||
fd.dwFileAttributes = FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_NORMAL;
|
FilePath fp = file->GetSiaPath();
|
||||||
FillFindData(&fd, DokanFileInfo);
|
fp.RemoveFileName();
|
||||||
}
|
if (std::find(files.begin(), files.end(), fp) == files.end())
|
||||||
|
{
|
||||||
|
WIN32_FIND_DATA fd = { 0 };
|
||||||
|
wcscpy_s(fd.cFileName, &fp[0]);
|
||||||
|
|
||||||
|
LARGE_INTEGER li = { 0 };
|
||||||
|
li.QuadPart = file->GetFileSize();
|
||||||
|
fd.nFileSizeHigh = li.HighPart;
|
||||||
|
fd.nFileSizeLow = li.LowPart;
|
||||||
|
fd.dwFileAttributes = FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_NORMAL;
|
||||||
|
fillFindData(&fd, dokanFileInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DOKAN_CALLBACK Sia_CloseFile(LPCWSTR FileName, PDOKAN_FILE_INFO DokanFileInfo)
|
static void DOKAN_CALLBACK Sia_CloseFile(LPCWSTR fileName, PDOKAN_FILE_INFO dokanFileInfo)
|
||||||
{
|
{
|
||||||
FilePath filePath(GetCacheLocation(), FileName);
|
FilePath filePath(GetCacheLocation(), fileName);
|
||||||
|
|
||||||
if (DokanFileInfo->Context)
|
if (dokanFileInfo->Context)
|
||||||
{
|
{
|
||||||
auto id = DokanFileInfo->Context;
|
auto id = dokanFileInfo->Context;
|
||||||
HANDLE handle = reinterpret_cast<HANDLE>(id);
|
HANDLE handle = reinterpret_cast<HANDLE>(id);
|
||||||
if (!DokanFileInfo->IsDirectory)
|
if (!dokanFileInfo->IsDirectory)
|
||||||
{
|
{
|
||||||
LARGE_INTEGER li = { 0 };
|
LARGE_INTEGER li = { 0 };
|
||||||
::GetFileSizeEx(handle, &li);
|
::GetFileSizeEx(handle, &li);
|
||||||
HandleFileClose(filePath, id, li.QuadPart);
|
HandleFileClose(filePath, id, li.QuadPart);
|
||||||
}
|
}
|
||||||
::CloseHandle(reinterpret_cast<HANDLE>(DokanFileInfo->Context));
|
::CloseHandle(reinterpret_cast<HANDLE>(dokanFileInfo->Context));
|
||||||
DokanFileInfo->Context = 0;
|
dokanFileInfo->Context = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS DOKAN_CALLBACK Sia_GetFileInformation(LPCWSTR FileName, LPBY_HANDLE_FILE_INFORMATION HandleFileInformation, PDOKAN_FILE_INFO DokanFileInfo)
|
static NTSTATUS DOKAN_CALLBACK Sia_GetFileInformation(LPCWSTR fileName, LPBY_HANDLE_FILE_INFORMATION handleFileInfo, PDOKAN_FILE_INFO dokanFileInfo)
|
||||||
{
|
{
|
||||||
HANDLE handle = reinterpret_cast<HANDLE>(DokanFileInfo->Context);
|
HANDLE handle = reinterpret_cast<HANDLE>(dokanFileInfo->Context);
|
||||||
BOOL opened = FALSE;
|
BOOL opened = FALSE;
|
||||||
NTSTATUS ret = STATUS_SUCCESS;
|
NTSTATUS ret = STATUS_SUCCESS;
|
||||||
|
|
||||||
FilePath cachePath = GetCacheLocation();
|
FilePath cachePath = GetCacheLocation();
|
||||||
if (FilePath::DirSep == FileName)
|
if (FilePath::DirSep == fileName)
|
||||||
{
|
{
|
||||||
cachePath.Append(FileName);
|
cachePath.Append(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!handle || (handle == INVALID_HANDLE_VALUE))
|
SString siaPath = CSiaApi::FormatToSiaPath(FilePath(fileName).SkipRoot());
|
||||||
|
auto siaFileTree = _siaFileTree;
|
||||||
|
auto siaFile = siaFileTree->GetFile(siaPath);
|
||||||
|
if (!siaFile && (!handle || (handle == INVALID_HANDLE_VALUE)))
|
||||||
{
|
{
|
||||||
handle = ::CreateFile(&cachePath[0], GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
|
handle = ::CreateFile(&cachePath[0], GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||||
if (handle == INVALID_HANDLE_VALUE)
|
if (handle == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
ret = DokanNtStatusFromWin32(GetLastError());
|
ret = DokanNtStatusFromWin32(::GetLastError());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -514,13 +549,13 @@ private:
|
|||||||
|
|
||||||
if (ret == STATUS_SUCCESS)
|
if (ret == STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
if (!::GetFileInformationByHandle(handle, HandleFileInformation))
|
if (!::GetFileInformationByHandle(handle, handleFileInfo))
|
||||||
{
|
{
|
||||||
// FileName is a root directory
|
// fileName is a root directory
|
||||||
// in this case, FindFirstFile can't get directory information
|
// in this case, FindFirstFile can't get directory information
|
||||||
if (wcslen(FileName) == 1)
|
if (wcslen(fileName) == 1)
|
||||||
{
|
{
|
||||||
HandleFileInformation->dwFileAttributes = ::GetFileAttributes(&cachePath[0]);
|
handleFileInfo->dwFileAttributes = ::GetFileAttributes(&cachePath[0]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -528,33 +563,45 @@ private:
|
|||||||
HANDLE findHandle = ::FindFirstFile(&cachePath[0], &find);
|
HANDLE findHandle = ::FindFirstFile(&cachePath[0], &find);
|
||||||
if (findHandle == INVALID_HANDLE_VALUE)
|
if (findHandle == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
// TODO Not Cached, so manual attributes
|
DWORD error = ::GetLastError();
|
||||||
ret = STATUS_SUCCESS;// DokanNtStatusFromWin32(::GetLastError());
|
if (siaFile)
|
||||||
|
{
|
||||||
|
LARGE_INTEGER li = { 0 };
|
||||||
|
li.QuadPart = siaFile->GetFileSize();
|
||||||
|
handleFileInfo->dwFileAttributes = FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_ARCHIVE;
|
||||||
|
handleFileInfo->nFileSizeHigh = li.HighPart;
|
||||||
|
handleFileInfo->nFileSizeLow = li.LowPart;
|
||||||
|
ret = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = DokanNtStatusFromWin32(error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
HandleFileInformation->dwFileAttributes = find.dwFileAttributes;
|
handleFileInfo->dwFileAttributes = find.dwFileAttributes;
|
||||||
HandleFileInformation->ftCreationTime = find.ftCreationTime;
|
handleFileInfo->ftCreationTime = find.ftCreationTime;
|
||||||
HandleFileInformation->ftLastAccessTime = find.ftLastAccessTime;
|
handleFileInfo->ftLastAccessTime = find.ftLastAccessTime;
|
||||||
HandleFileInformation->ftLastWriteTime = find.ftLastWriteTime;
|
handleFileInfo->ftLastWriteTime = find.ftLastWriteTime;
|
||||||
HandleFileInformation->nFileSizeHigh = find.nFileSizeHigh;
|
handleFileInfo->nFileSizeHigh = find.nFileSizeHigh;
|
||||||
HandleFileInformation->nFileSizeLow = find.nFileSizeLow;
|
handleFileInfo->nFileSizeLow = find.nFileSizeLow;
|
||||||
|
|
||||||
::FindClose(findHandle);
|
::FindClose(findHandle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (opened)
|
if (opened)
|
||||||
{
|
{
|
||||||
::CloseHandle(handle);
|
::CloseHandle(handle);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS DOKAN_CALLBACK Sia_Mounted(PDOKAN_FILE_INFO DokanFileInfo)
|
static NTSTATUS DOKAN_CALLBACK Sia_Mounted(PDOKAN_FILE_INFO dokanFileInfo)
|
||||||
{
|
{
|
||||||
// May spend a little wait time here while files are cleaned-up and re-added to queue
|
// May spend a little wait time here while files are cleaned-up and re-added to queue
|
||||||
_uploadManager.reset(new CUploadManager(CSiaCurl(_siaApi->GetHostConfig()), _siaDriveConfig));
|
_uploadManager.reset(new CUploadManager(CSiaCurl(_siaApi->GetHostConfig()), _siaDriveConfig));
|
||||||
@@ -564,7 +611,7 @@ private:
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS DOKAN_CALLBACK Sia_Unmounted(PDOKAN_FILE_INFO DokanFileInfo)
|
static NTSTATUS DOKAN_CALLBACK Sia_Unmounted(PDOKAN_FILE_INFO dokanFileInfo)
|
||||||
{
|
{
|
||||||
_uploadManager.reset(nullptr);
|
_uploadManager.reset(nullptr);
|
||||||
StopFileListThread();
|
StopFileListThread();
|
||||||
@@ -574,9 +621,9 @@ private:
|
|||||||
|
|
||||||
static NTSTATUS DOKAN_CALLBACK Sia_GetDiskFreeSpaceW(
|
static NTSTATUS DOKAN_CALLBACK Sia_GetDiskFreeSpaceW(
|
||||||
PULONGLONG FreeBytesAvailable, PULONGLONG TotalNumberOfBytes,
|
PULONGLONG FreeBytesAvailable, PULONGLONG TotalNumberOfBytes,
|
||||||
PULONGLONG TotalNumberOfFreeBytes, PDOKAN_FILE_INFO DokanFileInfo)
|
PULONGLONG TotalNumberOfFreeBytes, PDOKAN_FILE_INFO dokanFileInfo)
|
||||||
{
|
{
|
||||||
UNREFERENCED_PARAMETER(DokanFileInfo);
|
UNREFERENCED_PARAMETER(dokanFileInfo);
|
||||||
|
|
||||||
// TODO Implement this correctly
|
// TODO Implement this correctly
|
||||||
*FreeBytesAvailable = static_cast<ULONGLONG>(512 * 1024 * 1024);
|
*FreeBytesAvailable = static_cast<ULONGLONG>(512 * 1024 * 1024);
|
||||||
@@ -590,8 +637,8 @@ private:
|
|||||||
LPWSTR VolumeNameBuffer, DWORD VolumeNameSize, LPDWORD VolumeSerialNumber,
|
LPWSTR VolumeNameBuffer, DWORD VolumeNameSize, LPDWORD VolumeSerialNumber,
|
||||||
LPDWORD MaximumComponentLength, LPDWORD FileSystemFlags,
|
LPDWORD MaximumComponentLength, LPDWORD FileSystemFlags,
|
||||||
LPWSTR FileSystemNameBuffer, DWORD FileSystemNameSize,
|
LPWSTR FileSystemNameBuffer, DWORD FileSystemNameSize,
|
||||||
PDOKAN_FILE_INFO DokanFileInfo) {
|
PDOKAN_FILE_INFO dokanFileInfo) {
|
||||||
UNREFERENCED_PARAMETER(DokanFileInfo);
|
UNREFERENCED_PARAMETER(dokanFileInfo);
|
||||||
|
|
||||||
wcscpy_s(VolumeNameBuffer, VolumeNameSize, L"SiaDrive");
|
wcscpy_s(VolumeNameBuffer, VolumeNameSize, L"SiaDrive");
|
||||||
*VolumeSerialNumber = 0x19831116;
|
*VolumeSerialNumber = 0x19831116;
|
||||||
@@ -609,15 +656,15 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static NTSTATUS DOKAN_CALLBACK Sia_ReadFile(LPCWSTR FileName, LPVOID Buffer,
|
static NTSTATUS DOKAN_CALLBACK Sia_ReadFile(LPCWSTR fileName, LPVOID buffer,
|
||||||
DWORD BufferLength,
|
DWORD bufferLen,
|
||||||
LPDWORD ReadLength,
|
LPDWORD readLength,
|
||||||
LONGLONG Offset,
|
LONGLONG offset,
|
||||||
PDOKAN_FILE_INFO DokanFileInfo)
|
PDOKAN_FILE_INFO dokanFileInfo)
|
||||||
{
|
{
|
||||||
FilePath filePath(GetCacheLocation(), FileName);
|
FilePath filePath(GetCacheLocation(), fileName);
|
||||||
|
|
||||||
HANDLE handle = reinterpret_cast<HANDLE>(DokanFileInfo->Context);
|
HANDLE handle = reinterpret_cast<HANDLE>(dokanFileInfo->Context);
|
||||||
BOOL opened = FALSE;
|
BOOL opened = FALSE;
|
||||||
|
|
||||||
if (!handle || (handle == INVALID_HANDLE_VALUE))
|
if (!handle || (handle == INVALID_HANDLE_VALUE))
|
||||||
@@ -633,7 +680,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
LARGE_INTEGER distanceToMove;
|
LARGE_INTEGER distanceToMove;
|
||||||
distanceToMove.QuadPart = Offset;
|
distanceToMove.QuadPart = offset;
|
||||||
if (!::SetFilePointerEx(handle, distanceToMove, nullptr, FILE_BEGIN))
|
if (!::SetFilePointerEx(handle, distanceToMove, nullptr, FILE_BEGIN))
|
||||||
{
|
{
|
||||||
DWORD error = GetLastError();
|
DWORD error = GetLastError();
|
||||||
@@ -642,7 +689,7 @@ private:
|
|||||||
return DokanNtStatusFromWin32(error);
|
return DokanNtStatusFromWin32(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ReadFile(handle, Buffer, BufferLength, ReadLength, nullptr))
|
if (!ReadFile(handle, buffer, bufferLen, readLength, nullptr))
|
||||||
{
|
{
|
||||||
DWORD error = GetLastError();
|
DWORD error = GetLastError();
|
||||||
if (opened)
|
if (opened)
|
||||||
@@ -659,14 +706,14 @@ private:
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS DOKAN_CALLBACK Sia_WriteFile(LPCWSTR FileName, LPCVOID Buffer,
|
static NTSTATUS DOKAN_CALLBACK Sia_WriteFile(LPCWSTR fileName, LPCVOID buffer,
|
||||||
DWORD NumberOfBytesToWrite,
|
DWORD bytesToWrite,
|
||||||
LPDWORD NumberOfBytesWritten,
|
LPDWORD bytesWritten,
|
||||||
LONGLONG Offset,
|
LONGLONG offset,
|
||||||
PDOKAN_FILE_INFO DokanFileInfo)
|
PDOKAN_FILE_INFO dokanFileInfo)
|
||||||
{
|
{
|
||||||
FilePath filePath(GetCacheLocation(), FileName);
|
FilePath filePath(GetCacheLocation(), fileName);
|
||||||
HANDLE handle = reinterpret_cast<HANDLE>(DokanFileInfo->Context);
|
HANDLE handle = reinterpret_cast<HANDLE>(dokanFileInfo->Context);
|
||||||
BOOL opened = FALSE;
|
BOOL opened = FALSE;
|
||||||
|
|
||||||
// reopen the file
|
// reopen the file
|
||||||
@@ -692,46 +739,45 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
LARGE_INTEGER distanceToMove;
|
LARGE_INTEGER distanceToMove;
|
||||||
if (DokanFileInfo->WriteToEndOfFile)
|
if (dokanFileInfo->WriteToEndOfFile)
|
||||||
{
|
{
|
||||||
LARGE_INTEGER z;
|
LARGE_INTEGER z = {0};
|
||||||
z.QuadPart = 0;
|
|
||||||
if (!::SetFilePointerEx(handle, z, nullptr, FILE_END))
|
if (!::SetFilePointerEx(handle, z, nullptr, FILE_END))
|
||||||
{
|
{
|
||||||
DWORD error = GetLastError();
|
DWORD error = GetLastError();
|
||||||
if (opened)
|
if (opened)
|
||||||
CloseHandle(handle);
|
::CloseHandle(handle);
|
||||||
return DokanNtStatusFromWin32(error);
|
return DokanNtStatusFromWin32(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Paging IO cannot write after allocate file size.
|
// Paging IO cannot write after allocate file size.
|
||||||
if (DokanFileInfo->PagingIo)
|
if (dokanFileInfo->PagingIo)
|
||||||
{
|
{
|
||||||
if (static_cast<UINT64>(Offset) >= li.QuadPart)
|
if (static_cast<UINT64>(offset) >= li.QuadPart)
|
||||||
{
|
{
|
||||||
*NumberOfBytesWritten = 0;
|
*bytesWritten = 0;
|
||||||
if (opened)
|
if (opened)
|
||||||
CloseHandle(handle);
|
CloseHandle(handle);
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((static_cast<UINT64>(Offset) + NumberOfBytesToWrite) > li.QuadPart)
|
if ((static_cast<UINT64>(offset) + bytesToWrite) > li.QuadPart)
|
||||||
{
|
{
|
||||||
UINT64 bytes = li.QuadPart - Offset;
|
UINT64 bytes = li.QuadPart - offset;
|
||||||
if (bytes >> 32)
|
if (bytes >> 32)
|
||||||
{
|
{
|
||||||
NumberOfBytesToWrite = static_cast<DWORD>(bytes & 0xFFFFFFFFUL);
|
bytesToWrite = static_cast<DWORD>(bytes & 0xFFFFFFFFUL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NumberOfBytesToWrite = static_cast<DWORD>(bytes);
|
bytesToWrite = static_cast<DWORD>(bytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (static_cast<UINT64>(Offset) > li.QuadPart)
|
if (static_cast<UINT64>(offset) > li.QuadPart)
|
||||||
{
|
{
|
||||||
// In the mirror sample helperZeroFileData is not necessary. NTFS will
|
// In the mirror sample helperZeroFileData is not necessary. NTFS will
|
||||||
// zero a hole.
|
// zero a hole.
|
||||||
@@ -739,7 +785,7 @@ private:
|
|||||||
// file systems ) then users will have to zero the hole themselves.
|
// file systems ) then users will have to zero the hole themselves.
|
||||||
}
|
}
|
||||||
|
|
||||||
distanceToMove.QuadPart = Offset;
|
distanceToMove.QuadPart = offset;
|
||||||
if (!::SetFilePointerEx(handle, distanceToMove, nullptr, FILE_BEGIN))
|
if (!::SetFilePointerEx(handle, distanceToMove, nullptr, FILE_BEGIN))
|
||||||
{
|
{
|
||||||
DWORD error = GetLastError();
|
DWORD error = GetLastError();
|
||||||
@@ -749,7 +795,7 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (::WriteFile(handle, Buffer, NumberOfBytesToWrite, NumberOfBytesWritten, nullptr))
|
if (::WriteFile(handle, buffer, bytesToWrite, bytesWritten, nullptr))
|
||||||
{
|
{
|
||||||
// TODO Set status to changed
|
// TODO Set status to changed
|
||||||
}
|
}
|
||||||
@@ -768,11 +814,11 @@ private:
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS DOKAN_CALLBACK Sia_SetEndOfFile(LPCWSTR FileName, LONGLONG ByteOffset, PDOKAN_FILE_INFO DokanFileInfo)
|
static NTSTATUS DOKAN_CALLBACK Sia_SetEndOfFile(LPCWSTR fileName, LONGLONG byteOffset, PDOKAN_FILE_INFO dokanFileInfo)
|
||||||
{
|
{
|
||||||
NTSTATUS ret = STATUS_SUCCESS;
|
NTSTATUS ret = STATUS_SUCCESS;
|
||||||
|
|
||||||
HANDLE handle = reinterpret_cast<HANDLE>(DokanFileInfo->Context);
|
HANDLE handle = reinterpret_cast<HANDLE>(dokanFileInfo->Context);
|
||||||
if (!handle || (handle == INVALID_HANDLE_VALUE))
|
if (!handle || (handle == INVALID_HANDLE_VALUE))
|
||||||
{
|
{
|
||||||
ret = STATUS_INVALID_HANDLE;
|
ret = STATUS_INVALID_HANDLE;
|
||||||
@@ -781,7 +827,7 @@ private:
|
|||||||
{
|
{
|
||||||
// TODO Set status to changed
|
// TODO Set status to changed
|
||||||
LARGE_INTEGER offset;
|
LARGE_INTEGER offset;
|
||||||
offset.QuadPart = ByteOffset;
|
offset.QuadPart = byteOffset;
|
||||||
if (!::SetFilePointerEx(handle, offset, nullptr, FILE_BEGIN))
|
if (!::SetFilePointerEx(handle, offset, nullptr, FILE_BEGIN))
|
||||||
{
|
{
|
||||||
DWORD error = GetLastError();
|
DWORD error = GetLastError();
|
||||||
@@ -797,28 +843,28 @@ private:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DOKAN_CALLBACK Sia_Cleanup(LPCWSTR FileName, PDOKAN_FILE_INFO DokanFileInfo)
|
static void DOKAN_CALLBACK Sia_Cleanup(LPCWSTR fileName, PDOKAN_FILE_INFO dokanFileInfo)
|
||||||
{
|
{
|
||||||
FilePath filePath(GetCacheLocation(), FileName);
|
FilePath filePath(GetCacheLocation(), fileName);
|
||||||
if (DokanFileInfo->Context)
|
if (dokanFileInfo->Context)
|
||||||
{
|
{
|
||||||
HANDLE handle = reinterpret_cast<HANDLE>(DokanFileInfo->Context);
|
HANDLE handle = reinterpret_cast<HANDLE>(dokanFileInfo->Context);
|
||||||
if (!DokanFileInfo->IsDirectory)
|
if (!dokanFileInfo->IsDirectory)
|
||||||
{
|
{
|
||||||
LARGE_INTEGER li = { 0 };
|
LARGE_INTEGER li = { 0 };
|
||||||
::GetFileSizeEx(handle, &li);
|
::GetFileSizeEx(handle, &li);
|
||||||
HandleFileClose(filePath, DokanFileInfo->Context, li.QuadPart);
|
HandleFileClose(filePath, dokanFileInfo->Context, li.QuadPart);
|
||||||
}
|
}
|
||||||
|
|
||||||
::CloseHandle(handle);
|
::CloseHandle(handle);
|
||||||
DokanFileInfo->Context = 0;
|
dokanFileInfo->Context = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DokanFileInfo->DeleteOnClose)
|
if (dokanFileInfo->DeleteOnClose)
|
||||||
{
|
{
|
||||||
// Should already be deleted by CloseHandle
|
// Should already be deleted by CloseHandle
|
||||||
// if open with FILE_FLAG_DELETE_ON_CLOSE
|
// if open with FILE_FLAG_DELETE_ON_CLOSE
|
||||||
if (DokanFileInfo->IsDirectory)
|
if (dokanFileInfo->IsDirectory)
|
||||||
{
|
{
|
||||||
if (filePath.RemoveDirectory())
|
if (filePath.RemoveDirectory())
|
||||||
{
|
{
|
||||||
@@ -840,9 +886,9 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS DOKAN_CALLBACK Sia_FlushFileBuffers(LPCWSTR FileName, PDOKAN_FILE_INFO DokanFileInfo)
|
static NTSTATUS DOKAN_CALLBACK Sia_FlushFileBuffers(LPCWSTR fileName, PDOKAN_FILE_INFO dokanFileInfo)
|
||||||
{
|
{
|
||||||
HANDLE handle = reinterpret_cast<HANDLE>(DokanFileInfo->Context);
|
HANDLE handle = reinterpret_cast<HANDLE>(dokanFileInfo->Context);
|
||||||
if (!handle || (handle == INVALID_HANDLE_VALUE))
|
if (!handle || (handle == INVALID_HANDLE_VALUE))
|
||||||
{
|
{
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
@@ -859,11 +905,11 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS DOKAN_CALLBACK Sia_DeleteDirectory(LPCWSTR FileName, PDOKAN_FILE_INFO DokanFileInfo)
|
static NTSTATUS DOKAN_CALLBACK Sia_DeleteDirectory(LPCWSTR fileName, PDOKAN_FILE_INFO dokanFileInfo)
|
||||||
{
|
{
|
||||||
FilePath filePath = FilePath(GetCacheLocation(), FileName);
|
FilePath filePath = FilePath(GetCacheLocation(), fileName);
|
||||||
NTSTATUS ret = STATUS_SUCCESS;
|
NTSTATUS ret = STATUS_SUCCESS;
|
||||||
if (DokanFileInfo->DeleteOnClose)
|
if (dokanFileInfo->DeleteOnClose)
|
||||||
{
|
{
|
||||||
filePath.Append("*");
|
filePath.Append("*");
|
||||||
|
|
||||||
@@ -899,13 +945,13 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static NTSTATUS DOKAN_CALLBACK Sia_DeleteFileW(LPCWSTR FileName, PDOKAN_FILE_INFO DokanFileInfo)
|
static NTSTATUS DOKAN_CALLBACK Sia_DeleteFileW(LPCWSTR fileName, PDOKAN_FILE_INFO dokanFileInfo)
|
||||||
{
|
{
|
||||||
// TODO Handle files that aren't cached
|
// TODO Handle files that aren't cached
|
||||||
NTSTATUS ret = STATUS_SUCCESS;
|
NTSTATUS ret = STATUS_SUCCESS;
|
||||||
|
|
||||||
HANDLE handle = reinterpret_cast<HANDLE>(DokanFileInfo->Context);
|
HANDLE handle = reinterpret_cast<HANDLE>(dokanFileInfo->Context);
|
||||||
FilePath filePath(GetCacheLocation(), FileName);
|
FilePath filePath(GetCacheLocation(), fileName);
|
||||||
|
|
||||||
DWORD dwAttrib = ::GetFileAttributes(&filePath[0]);
|
DWORD dwAttrib = ::GetFileAttributes(&filePath[0]);
|
||||||
if ((dwAttrib != INVALID_FILE_ATTRIBUTES) && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY))
|
if ((dwAttrib != INVALID_FILE_ATTRIBUTES) && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY))
|
||||||
@@ -915,7 +961,7 @@ private:
|
|||||||
else if (handle && (handle != INVALID_HANDLE_VALUE))
|
else if (handle && (handle != INVALID_HANDLE_VALUE))
|
||||||
{
|
{
|
||||||
FILE_DISPOSITION_INFO fdi;
|
FILE_DISPOSITION_INFO fdi;
|
||||||
fdi.DeleteFile = DokanFileInfo->DeleteOnClose;
|
fdi.DeleteFile = dokanFileInfo->DeleteOnClose;
|
||||||
if (!::SetFileInformationByHandle(handle, FileDispositionInfo, &fdi, sizeof(FILE_DISPOSITION_INFO)))
|
if (!::SetFileInformationByHandle(handle, FileDispositionInfo, &fdi, sizeof(FILE_DISPOSITION_INFO)))
|
||||||
{
|
{
|
||||||
ret = DokanNtStatusFromWin32(GetLastError());
|
ret = DokanNtStatusFromWin32(GetLastError());
|
||||||
@@ -925,15 +971,15 @@ private:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS DOKAN_CALLBACK Sia_MoveFileW(LPCWSTR FileName, LPCWSTR NewFileName, BOOL ReplaceIfExisting, PDOKAN_FILE_INFO DokanFileInfo)
|
static NTSTATUS DOKAN_CALLBACK Sia_MoveFileW(LPCWSTR fileName, LPCWSTR NewFileName, BOOL ReplaceIfExisting, PDOKAN_FILE_INFO dokanFileInfo)
|
||||||
{
|
{
|
||||||
// TODO Handle files that aren't cached
|
// TODO Handle files that aren't cached
|
||||||
NTSTATUS ret = STATUS_SUCCESS;
|
NTSTATUS ret = STATUS_SUCCESS;
|
||||||
|
|
||||||
FilePath filePath(GetCacheLocation(), FileName);
|
FilePath filePath(GetCacheLocation(), fileName);
|
||||||
FilePath newFilePath(GetCacheLocation(), NewFileName);
|
FilePath newFilePath(GetCacheLocation(), NewFileName);
|
||||||
|
|
||||||
HANDLE handle = reinterpret_cast<HANDLE>(DokanFileInfo->Context);
|
HANDLE handle = reinterpret_cast<HANDLE>(dokanFileInfo->Context);
|
||||||
if (!handle || (handle == INVALID_HANDLE_VALUE))
|
if (!handle || (handle == INVALID_HANDLE_VALUE))
|
||||||
{
|
{
|
||||||
ret = STATUS_INVALID_HANDLE;
|
ret = STATUS_INVALID_HANDLE;
|
||||||
@@ -972,13 +1018,13 @@ private:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS DOKAN_CALLBACK Sia_SetFileAttributesW(LPCWSTR FileName, DWORD FileAttributes, PDOKAN_FILE_INFO DokanFileInfo)
|
static NTSTATUS DOKAN_CALLBACK Sia_SetFileAttributesW(LPCWSTR fileName, DWORD fileAttributes, PDOKAN_FILE_INFO dokanFileInfo)
|
||||||
{
|
{
|
||||||
UNREFERENCED_PARAMETER(DokanFileInfo);
|
UNREFERENCED_PARAMETER(dokanFileInfo);
|
||||||
NTSTATUS ret = STATUS_SUCCESS;
|
NTSTATUS ret = STATUS_SUCCESS;
|
||||||
|
|
||||||
FilePath filePath(GetCacheLocation(), FileName);
|
FilePath filePath(GetCacheLocation(), fileName);
|
||||||
if (!::SetFileAttributes(&filePath[0], FileAttributes))
|
if (!::SetFileAttributes(&filePath[0], fileAttributes))
|
||||||
{
|
{
|
||||||
DWORD error = GetLastError();
|
DWORD error = GetLastError();
|
||||||
ret = DokanNtStatusFromWin32(error);
|
ret = DokanNtStatusFromWin32(error);
|
||||||
@@ -988,19 +1034,19 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS DOKAN_CALLBACK Sia_GetFileSecurityW(
|
static NTSTATUS DOKAN_CALLBACK Sia_GetFileSecurityW(
|
||||||
LPCWSTR FileName, PSECURITY_INFORMATION SecurityInformation,
|
LPCWSTR fileName, PSECURITY_INFORMATION securityInfo,
|
||||||
PSECURITY_DESCRIPTOR SecurityDescriptor, ULONG BufferLength,
|
PSECURITY_DESCRIPTOR securityDescriptor, ULONG bufferLen,
|
||||||
PULONG LengthNeeded, PDOKAN_FILE_INFO DokanFileInfo)
|
PULONG lengthNeeded, PDOKAN_FILE_INFO dokanFileInfo)
|
||||||
{
|
{
|
||||||
UNREFERENCED_PARAMETER(DokanFileInfo);
|
UNREFERENCED_PARAMETER(dokanFileInfo);
|
||||||
FilePath filePath(GetCacheLocation(), FileName);
|
FilePath filePath(GetCacheLocation(), fileName);
|
||||||
SECURITY_INFORMATION requestingSaclInfo = ((*SecurityInformation & SACL_SECURITY_INFORMATION) || (*SecurityInformation & BACKUP_SECURITY_INFORMATION));
|
SECURITY_INFORMATION requestingSaclInfo = ((*securityInfo & SACL_SECURITY_INFORMATION) || (*securityInfo & BACKUP_SECURITY_INFORMATION));
|
||||||
|
|
||||||
//if (!g_HasSeSecurityPrivilege) {
|
//if (!g_HasSeSecurityPrivilege) {
|
||||||
if (true)
|
if (true)
|
||||||
{
|
{
|
||||||
*SecurityInformation &= ~SACL_SECURITY_INFORMATION;
|
*securityInfo &= ~SACL_SECURITY_INFORMATION;
|
||||||
*SecurityInformation &= ~BACKUP_SECURITY_INFORMATION;
|
*securityInfo &= ~BACKUP_SECURITY_INFORMATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
HANDLE handle = ::CreateFile(&filePath[0], READ_CONTROL | ((requestingSaclInfo && false) ? ACCESS_SYSTEM_SECURITY : 0),
|
HANDLE handle = ::CreateFile(&filePath[0], READ_CONTROL | ((requestingSaclInfo && false) ? ACCESS_SYSTEM_SECURITY : 0),
|
||||||
@@ -1016,7 +1062,7 @@ private:
|
|||||||
return DokanNtStatusFromWin32(error);
|
return DokanNtStatusFromWin32(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!::GetUserObjectSecurity(handle, SecurityInformation, SecurityDescriptor, BufferLength, LengthNeeded))
|
if (!::GetUserObjectSecurity(handle, securityInfo, securityDescriptor, bufferLen, lengthNeeded))
|
||||||
{
|
{
|
||||||
int error = ::GetLastError();
|
int error = ::GetLastError();
|
||||||
if (error == ERROR_INSUFFICIENT_BUFFER)
|
if (error == ERROR_INSUFFICIENT_BUFFER)
|
||||||
@@ -1037,21 +1083,21 @@ private:
|
|||||||
|
|
||||||
|
|
||||||
static NTSTATUS DOKAN_CALLBACK Sia_SetFileSecurityW(
|
static NTSTATUS DOKAN_CALLBACK Sia_SetFileSecurityW(
|
||||||
LPCWSTR FileName, PSECURITY_INFORMATION SecurityInformation,
|
LPCWSTR fileName, PSECURITY_INFORMATION securityInfo,
|
||||||
PSECURITY_DESCRIPTOR SecurityDescriptor, ULONG SecurityDescriptorLength,
|
PSECURITY_DESCRIPTOR securityDescriptor, ULONG securityDescriptorLength,
|
||||||
PDOKAN_FILE_INFO DokanFileInfo)
|
PDOKAN_FILE_INFO dokanFileInfo)
|
||||||
{
|
{
|
||||||
UNREFERENCED_PARAMETER(SecurityDescriptorLength);
|
UNREFERENCED_PARAMETER(securityDescriptorLength);
|
||||||
|
|
||||||
FilePath filePath(GetCacheLocation(), FileName);
|
FilePath filePath(GetCacheLocation(), fileName);
|
||||||
|
|
||||||
HANDLE handle = reinterpret_cast<HANDLE>(DokanFileInfo->Context);
|
HANDLE handle = reinterpret_cast<HANDLE>(dokanFileInfo->Context);
|
||||||
if (!handle || (handle == INVALID_HANDLE_VALUE))
|
if (!handle || (handle == INVALID_HANDLE_VALUE))
|
||||||
{
|
{
|
||||||
return STATUS_INVALID_HANDLE;
|
return STATUS_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!::SetUserObjectSecurity(handle, SecurityInformation, SecurityDescriptor))
|
if (!::SetUserObjectSecurity(handle, securityInfo, securityDescriptor))
|
||||||
{
|
{
|
||||||
int error = ::GetLastError();
|
int error = ::GetLastError();
|
||||||
return DokanNtStatusFromWin32(error);
|
return DokanNtStatusFromWin32(error);
|
||||||
@@ -1060,19 +1106,19 @@ private:
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS DOKAN_CALLBACK Sia_SetFileTime(LPCWSTR FileName, CONST FILETIME *CreationTime,
|
static NTSTATUS DOKAN_CALLBACK Sia_SetFileTime(LPCWSTR fileName, CONST FILETIME *creationTime,
|
||||||
CONST FILETIME *LastAccessTime, CONST FILETIME *LastWriteTime,
|
CONST FILETIME *lastAccessTime, CONST FILETIME *lastWriteTime,
|
||||||
PDOKAN_FILE_INFO DokanFileInfo)
|
PDOKAN_FILE_INFO dokanFileInfo)
|
||||||
{
|
{
|
||||||
FilePath filePath(GetCacheLocation(), FileName);
|
FilePath filePath(GetCacheLocation(), fileName);
|
||||||
|
|
||||||
HANDLE handle = reinterpret_cast<HANDLE>(DokanFileInfo->Context);
|
HANDLE handle = reinterpret_cast<HANDLE>(dokanFileInfo->Context);
|
||||||
if (!handle || (handle == INVALID_HANDLE_VALUE))
|
if (!handle || (handle == INVALID_HANDLE_VALUE))
|
||||||
{
|
{
|
||||||
return STATUS_INVALID_HANDLE;
|
return STATUS_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!::SetFileTime(handle, CreationTime, LastAccessTime, LastWriteTime))
|
if (!::SetFileTime(handle, creationTime, lastAccessTime, lastWriteTime))
|
||||||
{
|
{
|
||||||
DWORD error = GetLastError();
|
DWORD error = GetLastError();
|
||||||
return DokanNtStatusFromWin32(error);
|
return DokanNtStatusFromWin32(error);
|
||||||
@@ -1081,12 +1127,12 @@ private:
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS DOKAN_CALLBACK Sia_SetAllocationSize(LPCWSTR FileName, LONGLONG AllocSize, PDOKAN_FILE_INFO DokanFileInfo)
|
static NTSTATUS DOKAN_CALLBACK Sia_SetAllocationSize(LPCWSTR fileName, LONGLONG allocSize, PDOKAN_FILE_INFO dokanFileInfo)
|
||||||
{
|
{
|
||||||
NTSTATUS ret = STATUS_SUCCESS;
|
NTSTATUS ret = STATUS_SUCCESS;
|
||||||
FilePath filePath(GetCacheLocation(), FileName);
|
FilePath filePath(GetCacheLocation(), fileName);
|
||||||
|
|
||||||
HANDLE handle = reinterpret_cast<HANDLE>(DokanFileInfo->Context);
|
HANDLE handle = reinterpret_cast<HANDLE>(dokanFileInfo->Context);
|
||||||
if (!handle || (handle == INVALID_HANDLE_VALUE))
|
if (!handle || (handle == INVALID_HANDLE_VALUE))
|
||||||
{
|
{
|
||||||
ret = STATUS_INVALID_HANDLE;
|
ret = STATUS_INVALID_HANDLE;
|
||||||
@@ -1096,9 +1142,9 @@ private:
|
|||||||
LARGE_INTEGER fileSize = { 0 };
|
LARGE_INTEGER fileSize = { 0 };
|
||||||
if (::GetFileSizeEx(handle, &fileSize))
|
if (::GetFileSizeEx(handle, &fileSize))
|
||||||
{
|
{
|
||||||
if (AllocSize < fileSize.QuadPart)
|
if (allocSize < fileSize.QuadPart)
|
||||||
{
|
{
|
||||||
fileSize.QuadPart = AllocSize;
|
fileSize.QuadPart = allocSize;
|
||||||
if (!::SetFilePointerEx(handle, fileSize, nullptr, FILE_BEGIN))
|
if (!::SetFilePointerEx(handle, fileSize, nullptr, FILE_BEGIN))
|
||||||
{
|
{
|
||||||
DWORD error = GetLastError();
|
DWORD error = GetLastError();
|
||||||
@@ -1217,7 +1263,7 @@ std::unique_ptr<CUploadManager> DokanImpl::_uploadManager;
|
|||||||
DOKAN_OPERATIONS DokanImpl::_dokanOps;
|
DOKAN_OPERATIONS DokanImpl::_dokanOps;
|
||||||
DOKAN_OPTIONS DokanImpl::_dokanOptions;
|
DOKAN_OPTIONS DokanImpl::_dokanOptions;
|
||||||
FilePath DokanImpl::_cacheLocation;
|
FilePath DokanImpl::_cacheLocation;
|
||||||
bool DokanImpl::_fileListStopRequested;
|
HANDLE DokanImpl::_fileListStopEvent;
|
||||||
CSiaFileTreePtr DokanImpl::_siaFileTree;
|
CSiaFileTreePtr DokanImpl::_siaFileTree;
|
||||||
std::mutex DokanImpl::_fileTreeMutex;
|
std::mutex DokanImpl::_fileTreeMutex;
|
||||||
std::unique_ptr<std::thread> DokanImpl::_fileListThread;
|
std::unique_ptr<std::thread> DokanImpl::_fileListThread;
|
||||||
|
Reference in New Issue
Block a user