From 6f21dd78806297e058ad2930c55b500054af53c2 Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Sat, 11 Feb 2017 01:46:15 -0600 Subject: [PATCH] Dokan changes --- SiaDrive.Api/SiaApi.cpp | 8 +- SiaDrive.Api/SiaApi.h | 24 ++- SiaDrive.Api/SiaDrive.Api.vcxproj | 1 + SiaDrive.Api/SiaDrive.Api.vcxproj.filters | 3 + SiaDrive.Api/SiaRenter.cpp | 24 +++ SiaDrive.Dokan.Api/SiaDokanDrive.cpp | 179 ++++++++++++++++++++-- SiaDrive.Dokan.Api/SiaDokanDrive.h | 8 +- 7 files changed, 231 insertions(+), 16 deletions(-) create mode 100644 SiaDrive.Api/SiaRenter.cpp diff --git a/SiaDrive.Api/SiaApi.cpp b/SiaDrive.Api/SiaApi.cpp index e3b39dc..98a14ba 100644 --- a/SiaDrive.Api/SiaApi.cpp +++ b/SiaDrive.Api/SiaApi.cpp @@ -5,7 +5,8 @@ using namespace Sia::Api; CSiaApi::CSiaApi(const SiaHostConfig& hostConfig) : _siaCurl(hostConfig), - _wallet(new CSiaWallet(_siaCurl)) + _wallet(new CSiaWallet(_siaCurl)), + _renter(new CSiaRenter(_siaCurl)) { } @@ -23,4 +24,9 @@ String CSiaApi::GetServerVersion() const CSiaWalletPtr CSiaApi::GetWallet() const { return _wallet; +} + +CSiaRenterPtr CSiaApi::GetRenter() const +{ + return _renter; } \ No newline at end of file diff --git a/SiaDrive.Api/SiaApi.h b/SiaDrive.Api/SiaApi.h index 49deae1..694798d 100644 --- a/SiaDrive.Api/SiaApi.h +++ b/SiaDrive.Api/SiaApi.h @@ -52,6 +52,23 @@ public: _SiaApiError GetUnonfirmedBalance(SiaCurrency& balance) const; }; + class AFX_EXT_CLASS _CSiaRenter + { + friend CSiaApi; + private: + _CSiaRenter(CSiaCurl& siaCurl); + + public: + ~_CSiaRenter(); + + private: + CSiaCurl& _siaCurl; + + public: + _SiaApiError FileExists(const String& siaPath, bool& exists) const; + _SiaApiError DeleteFile(const String& siaPath); + }; + public: CSiaApi(const SiaHostConfig& hostConfig); @@ -61,16 +78,19 @@ public: private: CSiaCurl _siaCurl; std::shared_ptr<_CSiaWallet> _wallet; + std::shared_ptr<_CSiaRenter> _renter; public: std::shared_ptr<_CSiaWallet> GetWallet() const; + std::shared_ptr<_CSiaRenter> GetRenter() const; String GetServerVersion() const; - }; typedef CSiaApi::_SiaApiError SiaApiError; typedef CSiaApi::_SiaSeedLanguage SiaSeedLanguage; typedef CSiaApi::_CSiaWallet CSiaWallet; -typedef std::shared_ptr CSiaWalletPtr; +typedef CSiaApi::_CSiaRenter CSiaRenter; +typedef std::shared_ptr CSiaWalletPtr; +typedef std::shared_ptr CSiaRenterPtr; NS_END(2) \ No newline at end of file diff --git a/SiaDrive.Api/SiaDrive.Api.vcxproj b/SiaDrive.Api/SiaDrive.Api.vcxproj index 5d98a40..1dcbb9c 100644 --- a/SiaDrive.Api/SiaDrive.Api.vcxproj +++ b/SiaDrive.Api/SiaDrive.Api.vcxproj @@ -196,6 +196,7 @@ + Create diff --git a/SiaDrive.Api/SiaDrive.Api.vcxproj.filters b/SiaDrive.Api/SiaDrive.Api.vcxproj.filters index 9c70272..b75dcec 100644 --- a/SiaDrive.Api/SiaDrive.Api.vcxproj.filters +++ b/SiaDrive.Api/SiaDrive.Api.vcxproj.filters @@ -39,6 +39,9 @@ Source Files + + Source Files + diff --git a/SiaDrive.Api/SiaRenter.cpp b/SiaDrive.Api/SiaRenter.cpp new file mode 100644 index 0000000..ddb419f --- /dev/null +++ b/SiaDrive.Api/SiaRenter.cpp @@ -0,0 +1,24 @@ +#include "stdafx.h" +#include "SiaApi.h" + +using namespace Sia::Api; + +CSiaApi::_CSiaRenter::_CSiaRenter(CSiaCurl& siaCurl) : + _siaCurl(siaCurl) +{ +} + +CSiaApi::_CSiaRenter::~_CSiaRenter() +{ + +} + +SiaApiError CSiaApi::_CSiaRenter::FileExists(const String& siaPath, bool& exists) const +{ + return SiaApiError::NotImplemented; +} + +SiaApiError CSiaApi::_CSiaRenter::DeleteFile(const String& siaPath) +{ + return SiaApiError::NotImplemented; +} \ No newline at end of file diff --git a/SiaDrive.Dokan.Api/SiaDokanDrive.cpp b/SiaDrive.Dokan.Api/SiaDokanDrive.cpp index 7429e44..6fe843b 100644 --- a/SiaDrive.Dokan.Api/SiaDokanDrive.cpp +++ b/SiaDrive.Dokan.Api/SiaDokanDrive.cpp @@ -1,16 +1,19 @@ #include "stdafx.h" #include "SiaDokanDrive.h" #include +#include using namespace Sia::Api; using namespace Sia::Api::Dokan; + class DokanImpl { private: static std::mutex _dokanMutex; static CSiaApi* _siaApi; static DOKAN_OPERATIONS _dokanOps; + static String _cacheLocation; private: static NTSTATUS DOKAN_CALLBACK SiaDrive_ZwCreateFile( @@ -23,6 +26,162 @@ private: ULONG CreateOptions, PDOKAN_FILE_INFO DokanFileInfo) { + SECURITY_ATTRIBUTES securityAttrib; + securityAttrib.nLength = sizeof(securityAttrib); + securityAttrib.lpSecurityDescriptor = SecurityContext->AccessState.SecurityDescriptor; + securityAttrib.bInheritHandle = FALSE; + + DWORD fileAttributesAndFlags; + DWORD creationDisposition; + DokanMapKernelToUserCreateFileFlags(FileAttributes, CreateOptions, CreateDisposition, &fileAttributesAndFlags, &creationDisposition); + + ACCESS_MASK genericDesiredAccess = DokanMapStandardToGenericAccess(DesiredAccess); + + NTSTATUS ret = STATUS_SUCCESS; + bool isFile = (fileAttributesAndFlags & FILE_NON_DIRECTORY_FILE); + if (isFile) + { + // Formulate Sia path and cache path + String siaPath = PathSkipRoot(FileName); // Strip drive letter to get Sia path + + String cacheFilePath; + cacheFilePath.resize(MAX_PATH + 1); + PathCombine(&cacheFilePath[0], _cacheLocation.c_str(), siaPath.c_str()); + + // If cache file already exists and is a directory, file operation should fail + if (GetFileAttributes(cacheFilePath.c_str()) & FILE_ATTRIBUTE_DIRECTORY) + { + ret = STATUS_OBJECT_NAME_COLLISION; + } + else + { + bool exists; + if (API_SUCCESS(SiaApiError, _siaApi->GetRenter()->FileExists(siaPath, exists))) + { + bool isCreateOp = false; + bool isReplaceOp = false; + switch (creationDisposition) + { + case CREATE_ALWAYS: + { + isCreateOp = true; + isReplaceOp = exists; + } + break; + + case CREATE_NEW: + { + if (exists) + { + ret = STATUS_OBJECT_NAME_EXISTS; + } + else + { + isCreateOp = true; + } + } + break; + + case OPEN_ALWAYS: + { + if (!exists) + { + isCreateOp = true; + } + } + break; + + case OPEN_EXISTING: + { + if (!exists) + { + ret = STATUS_NOT_FOUND; + } + } + break; + + case TRUNCATE_EXISTING: + { + if (exists) + { + isCreateOp = isReplaceOp = true; + } + else + { + ret = STATUS_NOT_FOUND; + } + } + break; + } + + if (ret == STATUS_SUCCESS) + { + if (isReplaceOp) + { + if (!PathFileExists(cacheFilePath.c_str()) || ::DeleteFile(cacheFilePath.c_str())) + { + // Delete from Sia + if (!API_SUCCESS(SiaApiError, _siaApi->GetRenter()->DeleteFile(siaPath))) + { + ret = STATUS_INVALID_SERVER_STATE; + } + } + else + { + ret = DokanNtStatusFromWin32(GetLastError()); + } + } + + if (ret == STATUS_SUCCESS) + { + // If file should exist, then check for it in cache location. If not found, + // it must be downloaded first + if (!isCreateOp && !PathFileExists(cacheFilePath.c_str())) + { + + } + + HANDLE handle = CreateFile( + cacheFilePath.c_str(), + genericDesiredAccess, + ShareAccess, + &securityAttrib, + creationDisposition, + fileAttributesAndFlags, + nullptr); + if (handle == INVALID_HANDLE_VALUE) + { + ret = DokanNtStatusFromWin32(GetLastError()); + } + else + { + DokanFileInfo->Context = reinterpret_cast(handle); // save the file handle in Context + /*if (creationDisposition == OPEN_ALWAYS || + creationDisposition == CREATE_ALWAYS) { + error = GetLastError(); + if (error == ERROR_ALREADY_EXISTS) { + DbgPrint(L"\tOpen an already existing file\n"); + // Open succeed but we need to inform the driver + // that the file open and not created by returning STATUS_OBJECT_NAME_COLLISION + return STATUS_OBJECT_NAME_COLLISION; + } + }*/ + } + } + } + } + else + { + ret = STATUS_INVALID_SERVER_STATE; + } + } + } + else // Folder Operation (cache operation only) + { + ret = STATUS_NOT_IMPLEMENTED; + } + + return ret; } static NTSTATUS DOKAN_CALLBACK SiaDrive_FindFiles( @@ -30,6 +189,7 @@ private: PFillFindData FillFindData, PDOKAN_FILE_INFO DokanFileInfo) { + return 0; } public: @@ -81,20 +241,19 @@ public: }; std::mutex DokanImpl::_dokanMutex; CSiaApi* DokanImpl::_siaApi = nullptr; -DOKAN_OPERATIONS DokanImpl::_dokanOps = { 0 }; +DOKAN_OPERATIONS DokanImpl::_dokanOps; +String DokanImpl::_cacheLocation; + CSiaDokanDrive::CSiaDokanDrive(CSiaApi& siaApi) : - _siaApi(siaApi) + _siaApi(siaApi), + _Mounted(false) { std::lock_guard l(DokanImpl::GetMutex()); if (DokanImpl::IsInitialized()) - { throw SiaDokanDriveException("Sia drive has already been activated"); - } - else - { - DokanImpl::Initialize(&_siaApi); - } + + DokanImpl::Initialize(&_siaApi); } CSiaDokanDrive::~CSiaDokanDrive() @@ -104,10 +263,10 @@ CSiaDokanDrive::~CSiaDokanDrive() DokanImpl::Shutdown(); } -void CSiaDokanDrive::Mount(const wchar_t& driveLetter) +void CSiaDokanDrive::Mount(const wchar_t& driveLetter, const String& cacheLocation, const std::uint64_t& maxCacheSizeBytes) { } -void CSiaDokanDrive::Unmount() +void CSiaDokanDrive::Unmount(const bool& clearCache) { } \ No newline at end of file diff --git a/SiaDrive.Dokan.Api/SiaDokanDrive.h b/SiaDrive.Dokan.Api/SiaDokanDrive.h index 650a19f..c229ae8 100644 --- a/SiaDrive.Dokan.Api/SiaDokanDrive.h +++ b/SiaDrive.Dokan.Api/SiaDokanDrive.h @@ -29,10 +29,12 @@ public: private: CSiaApi& _siaApi; -public: - void Mount(const wchar_t& driveLetter); + Property(bool, Mounted, public, private) - void Unmount( ); +public: + void Mount(const wchar_t& driveLetter, const String& cacheLocation, const std::uint64_t& maxCacheSizeBytes); + + void Unmount(const bool& clearCache = false); }; NS_END(3) \ No newline at end of file