diff --git a/SiaDrive.Api/SiaFileTree.cpp b/SiaDrive.Api/SiaFileTree.cpp index e485771..9d41a5d 100644 --- a/SiaDrive.Api/SiaFileTree.cpp +++ b/SiaDrive.Api/SiaFileTree.cpp @@ -86,10 +86,16 @@ std::vector CSiaApi::_CSiaFileTree::QueryDirectories(String rootFolder) if ((dir.length() > rootFolder.length()) && (dir.substr(0, rootFolder.length()) == rootFolder)) { String subFolder = dir.substr(rootFolder.length()); - int f = subFolder.find_first_of('\\'); - if (f > 0) + int idx = subFolder.find_first_of('\\'); + if (idx == 0) { - subFolder = subFolder.substr(0, f); + subFolder = subFolder.substr(1); + idx = subFolder.find_first_of('\\'); + } + + if (idx > 0) + { + subFolder = subFolder.substr(0, idx); } auto it = std::find(ret.begin(), ret.end(), subFolder); diff --git a/SiaDrive.Dokan.Api/SiaDokanDrive.cpp b/SiaDrive.Dokan.Api/SiaDokanDrive.cpp index 0e87074..0563ed9 100644 --- a/SiaDrive.Dokan.Api/SiaDokanDrive.cpp +++ b/SiaDrive.Dokan.Api/SiaDokanDrive.cpp @@ -158,7 +158,7 @@ private: ::PathCombine(&cacheFilePath[0], GetCacheLocation().c_str(), &FileName[1]); DWORD fileAttr = ::GetFileAttributes(cacheFilePath.c_str()); - if (fileAttr != INVALID_FILE_ATTRIBUTES && + if ((fileAttr != INVALID_FILE_ATTRIBUTES) && (fileAttr & FILE_ATTRIBUTE_DIRECTORY) && !(CreateOptions & FILE_NON_DIRECTORY_FILE)) { @@ -170,12 +170,25 @@ private: } } - if (!DokanFileInfo->IsDirectory) + // Folder (cache operation only) + if (DokanFileInfo->IsDirectory) + { + HANDLE handle = ::CreateFile(cacheFilePath.c_str(), genericDesiredAccess, ShareAccess, &securityAttrib, creationDisposition, fileAttributesAndFlags | FILE_FLAG_BACKUP_SEMANTICS, nullptr); + if (handle == INVALID_HANDLE_VALUE) + { + ret = DokanNtStatusFromWin32(GetLastError()); + } + else + { + DokanFileInfo->Context = reinterpret_cast(handle); // save the file handle in Context + } + } + else // File (cache and/or Sia operation) { // Formulate Sia path and cache path String siaPath = CSiaApi::FormatToSiaPath(PathSkipRoot(FileName)); // Strip drive letter to get Sia path if (siaPath.length()) - { + { // If cache file already exists and is a directory, requested file operation isn't valid DWORD attribs = ::GetFileAttributes(cacheFilePath.c_str()); if ((attribs != INVALID_FILE_ATTRIBUTES) && (attribs & FILE_ATTRIBUTE_DIRECTORY)) @@ -309,15 +322,15 @@ private: _openFileMap.insert({ DokanFileInfo->Context, ofi }); /*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; - } - }*/ + 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; + } + }*/ } } } @@ -334,18 +347,6 @@ private: ret = STATUS_OBJECT_NAME_INVALID; } } - else // Folder Operation (cache operation only) - { - HANDLE handle = ::CreateFile(cacheFilePath.c_str(), genericDesiredAccess, ShareAccess, &securityAttrib, creationDisposition, fileAttributesAndFlags | FILE_FLAG_BACKUP_SEMANTICS, nullptr); - if (handle == INVALID_HANDLE_VALUE) - { - ret = DokanNtStatusFromWin32(GetLastError()); - } - else - { - DokanFileInfo->Context = reinterpret_cast(handle); // save the file handle in Context - } - } } return ret; @@ -357,16 +358,30 @@ private: auto siaFileTree = _siaFileTree; if (siaFileTree) { - String siaQuery = CSiaApi::FormatToSiaPath(PathSkipRoot(FileName)); - String rootPath = FileName; - if (::PathIsDirectory(FileName)) + String siaQuery = CSiaApi::FormatToSiaPath(::PathSkipRoot(FileName)); + + String cachePath; + String rootPath = siaQuery; + if (wcscmp(FileName, L"\\") == 0) { + cachePath = GetCacheLocation().c_str(); siaQuery += L"/*.*"; } else { - ::PathRemoveFileSpec(&rootPath[0]); - rootPath = rootPath.c_str(); + cachePath.resize(MAX_PATH + 1); + ::PathCombine(&cachePath[0], GetCacheLocation().c_str(), &FileName[1]); + cachePath = cachePath.c_str(); + if (::GetFileAttributes(&cachePath[0]) & FILE_ATTRIBUTE_DIRECTORY) + { + siaQuery += L"/*.*"; + } + else + { + rootPath = cachePath; + ::PathRemoveFileSpec(&rootPath[0]); + rootPath = CSiaApi::FormatToSiaPath(rootPath); + } } auto dirList = siaFileTree->QueryDirectories(rootPath); @@ -374,22 +389,15 @@ private: { WIN32_FIND_DATA fd = { 0 }; wcscpy_s(fd.cFileName, dir.c_str()); - fd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; - String cachePath; - cachePath.resize(MAX_PATH + 1); - if (rootPath == L"\\") - { - ::PathCombine(&cachePath[0], GetCacheLocation().c_str(), dir.c_str()); - } - else - { - ::PathCombine(&cachePath[0], GetCacheLocation().c_str(), rootPath.c_str()); - ::PathAppend(&cachePath[0], dir.c_str()); - } - cachePath = cachePath.c_str(); - ::CreateDirectory(cachePath.c_str(), nullptr); FillFindData(&fd, DokanFileInfo); + + // Create cache sub-folder + String subCachePath = cachePath.c_str(); + subCachePath.resize(MAX_PATH + 1); + ::PathAppend(&subCachePath[0], dir.c_str()); + subCachePath = subCachePath.c_str(); + ::CreateDirectory(subCachePath.c_str(), nullptr); } auto fileList = siaFileTree->Query(siaQuery);