Merge pull request #3461 from mmdanggg2/master

Fix crash in cldapi.dll
This commit is contained in:
Matthieu Gallien 2022-09-05 10:15:57 +02:00 committed by GitHub
commit bf3304441d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 43 additions and 67 deletions

View file

@ -649,6 +649,8 @@ OCC::CfApiWrapper::FileHandle OCC::CfApiWrapper::handleForPath(const QString &pa
const qint64 openResult = CfOpenFileWithOplock(path.toStdWString().data(), CF_OPEN_FILE_FLAG_NONE, &handle); const qint64 openResult = CfOpenFileWithOplock(path.toStdWString().data(), CF_OPEN_FILE_FLAG_NONE, &handle);
if (openResult == S_OK) { if (openResult == S_OK) {
return {handle, [](HANDLE h) { CfCloseHandle(h); }}; return {handle, [](HANDLE h) { CfCloseHandle(h); }};
} else {
qCWarning(lcCfApiWrapper) << "Could not open handle for " << path << " result: " << QString::fromWCharArray(_com_error(openResult).ErrorMessage());
} }
} else if (pathFileInfo.isFile()) { } else if (pathFileInfo.isFile()) {
const auto longpath = OCC::FileSystem::longWinPath(path); const auto longpath = OCC::FileSystem::longWinPath(path);
@ -664,14 +666,12 @@ OCC::CfApiWrapper::FileHandle OCC::CfApiWrapper::handleForPath(const QString &pa
return {}; return {};
} }
OCC::CfApiWrapper::PlaceHolderInfo OCC::CfApiWrapper::findPlaceholderInfo(const FileHandle &handle) OCC::CfApiWrapper::PlaceHolderInfo OCC::CfApiWrapper::findPlaceholderInfo(const QString &path)
{ {
Q_ASSERT(handle);
constexpr auto fileIdMaxLength = 128; constexpr auto fileIdMaxLength = 128;
const auto infoSize = sizeof(CF_PLACEHOLDER_BASIC_INFO) + fileIdMaxLength; const auto infoSize = sizeof(CF_PLACEHOLDER_BASIC_INFO) + fileIdMaxLength;
auto info = PlaceHolderInfo(reinterpret_cast<CF_PLACEHOLDER_BASIC_INFO *>(new char[infoSize]), deletePlaceholderInfo); auto info = PlaceHolderInfo(reinterpret_cast<CF_PLACEHOLDER_BASIC_INFO *>(new char[infoSize]), deletePlaceholderInfo);
const qint64 result = CfGetPlaceholderInfo(handle.get(), CF_PLACEHOLDER_INFO_BASIC, info.get(), sizeToDWORD(infoSize), nullptr); const qint64 result = CfGetPlaceholderInfo(handleForPath(path).get(), CF_PLACEHOLDER_INFO_BASIC, info.get(), sizeToDWORD(infoSize), nullptr);
if (result == S_OK) { if (result == S_OK) {
return info; return info;
@ -680,16 +680,16 @@ OCC::CfApiWrapper::PlaceHolderInfo OCC::CfApiWrapper::findPlaceholderInfo(const
} }
} }
OCC::Result<OCC::Vfs::ConvertToPlaceholderResult, QString> OCC::CfApiWrapper::setPinState(const FileHandle &handle, OCC::PinStateEnums::PinState state, SetPinRecurseMode mode) OCC::Result<OCC::Vfs::ConvertToPlaceholderResult, QString> OCC::CfApiWrapper::setPinState(const QString &path, OCC::PinStateEnums::PinState state, SetPinRecurseMode mode)
{ {
const auto cfState = pinStateToCfPinState(state); const auto cfState = pinStateToCfPinState(state);
const auto flags = pinRecurseModeToCfSetPinFlags(mode); const auto flags = pinRecurseModeToCfSetPinFlags(mode);
const qint64 result = CfSetPinState(handle.get(), cfState, flags, nullptr); const qint64 result = CfSetPinState(handleForPath(path).get(), cfState, flags, nullptr);
if (result == S_OK) { if (result == S_OK) {
return OCC::Vfs::ConvertToPlaceholderResult::Ok; return OCC::Vfs::ConvertToPlaceholderResult::Ok;
} else { } else {
qCWarning(lcCfApiWrapper) << "Couldn't set pin state" << state << "for" << pathForHandle(handle) << "with recurse mode" << mode << ":" << QString::fromWCharArray(_com_error(result).ErrorMessage()); qCWarning(lcCfApiWrapper) << "Couldn't set pin state" << state << "for" << path << "with recurse mode" << mode << ":" << QString::fromWCharArray(_com_error(result).ErrorMessage());
return { "Couldn't set pin state" }; return { "Couldn't set pin state" };
} }
} }
@ -732,28 +732,25 @@ OCC::Result<void, QString> OCC::CfApiWrapper::createPlaceholderInfo(const QStrin
return { "Couldn't create placeholder info" }; return { "Couldn't create placeholder info" };
} }
const auto parentHandle = handleForPath(QDir::toNativeSeparators(QFileInfo(path).absolutePath())); const auto parentInfo = findPlaceholderInfo(QDir::toNativeSeparators(QFileInfo(path).absolutePath()));
const auto parentInfo = findPlaceholderInfo(parentHandle);
const auto state = parentInfo && parentInfo->PinState == CF_PIN_STATE_UNPINNED ? CF_PIN_STATE_UNPINNED : CF_PIN_STATE_INHERIT; const auto state = parentInfo && parentInfo->PinState == CF_PIN_STATE_UNPINNED ? CF_PIN_STATE_UNPINNED : CF_PIN_STATE_INHERIT;
const auto handle = handleForPath(path); if (!setPinState(path, cfPinStateToPinState(state), NoRecurse)) {
if (!setPinState(handle, cfPinStateToPinState(state), NoRecurse)) {
return { "Couldn't set the default inherit pin state" }; return { "Couldn't set the default inherit pin state" };
} }
return {}; return {};
} }
OCC::Result<OCC::Vfs::ConvertToPlaceholderResult, QString> OCC::CfApiWrapper::updatePlaceholderInfo(const FileHandle &handle, time_t modtime, qint64 size, const QByteArray &fileId, const QString &replacesPath) OCC::Result<OCC::Vfs::ConvertToPlaceholderResult, QString> OCC::CfApiWrapper::updatePlaceholderInfo(const QString &path, time_t modtime, qint64 size, const QByteArray &fileId, const QString &replacesPath)
{ {
Q_ASSERT(handle);
if (modtime <= 0) { if (modtime <= 0) {
return {QString{"Could not update metadata due to invalid modification time for %1: %2"}.arg(pathForHandle(handle)).arg(modtime)}; return {QString{"Could not update metadata due to invalid modification time for %1: %2"}.arg(path).arg(modtime)};
} }
const auto info = replacesPath.isEmpty() ? findPlaceholderInfo(handle) const auto info = replacesPath.isEmpty() ? findPlaceholderInfo(path)
: findPlaceholderInfo(handleForPath(replacesPath)); : findPlaceholderInfo(replacesPath);
if (!info) { if (!info) {
return { "Can't update non existing placeholder info" }; return { "Can't update non existing placeholder info" };
} }
@ -770,32 +767,30 @@ OCC::Result<OCC::Vfs::ConvertToPlaceholderResult, QString> OCC::CfApiWrapper::up
OCC::Utility::UnixTimeToLargeIntegerFiletime(modtime, &metadata.BasicInfo.ChangeTime); OCC::Utility::UnixTimeToLargeIntegerFiletime(modtime, &metadata.BasicInfo.ChangeTime);
metadata.BasicInfo.FileAttributes = 0; metadata.BasicInfo.FileAttributes = 0;
const qint64 result = CfUpdatePlaceholder(handle.get(), &metadata, const qint64 result = CfUpdatePlaceholder(handleForPath(path).get(), &metadata,
fileIdentity.data(), sizeToDWORD(fileIdentitySize), fileIdentity.data(), sizeToDWORD(fileIdentitySize),
nullptr, 0, CF_UPDATE_FLAG_MARK_IN_SYNC, nullptr, nullptr); nullptr, 0, CF_UPDATE_FLAG_MARK_IN_SYNC, nullptr, nullptr);
if (result != S_OK) { if (result != S_OK) {
qCWarning(lcCfApiWrapper) << "Couldn't update placeholder info for" << pathForHandle(handle) << ":" << QString::fromWCharArray(_com_error(result).ErrorMessage()) << replacesPath; qCWarning(lcCfApiWrapper) << "Couldn't update placeholder info for" << path << ":" << QString::fromWCharArray(_com_error(result).ErrorMessage()) << replacesPath;
return { "Couldn't update placeholder info" }; return { "Couldn't update placeholder info" };
} }
// Pin state tends to be lost on updates, so restore it every time // Pin state tends to be lost on updates, so restore it every time
if (!setPinState(handle, previousPinState, NoRecurse)) { if (!setPinState(path, previousPinState, NoRecurse)) {
return { "Couldn't restore pin state" }; return { "Couldn't restore pin state" };
} }
return OCC::Vfs::ConvertToPlaceholderResult::Ok; return OCC::Vfs::ConvertToPlaceholderResult::Ok;
} }
OCC::Result<OCC::Vfs::ConvertToPlaceholderResult, QString> OCC::CfApiWrapper::dehydratePlaceholder(const FileHandle &handle, time_t modtime, qint64 size, const QByteArray &fileId) OCC::Result<OCC::Vfs::ConvertToPlaceholderResult, QString> OCC::CfApiWrapper::dehydratePlaceholder(const QString &path, time_t modtime, qint64 size, const QByteArray &fileId)
{ {
Q_ASSERT(handle);
if (modtime <= 0) { if (modtime <= 0) {
return {QString{"Could not update metadata due to invalid modification time for %1: %2"}.arg(pathForHandle(handle)).arg(modtime)}; return {QString{"Could not update metadata due to invalid modification time for %1: %2"}.arg(path).arg(modtime)};
} }
const auto info = findPlaceholderInfo(handle); const auto info = findPlaceholderInfo(path);
if (!info) { if (!info) {
return { "Can't update non existing placeholder info" }; return { "Can't update non existing placeholder info" };
} }
@ -807,43 +802,40 @@ OCC::Result<OCC::Vfs::ConvertToPlaceholderResult, QString> OCC::CfApiWrapper::de
dehydrationRange.StartingOffset.QuadPart = 0; dehydrationRange.StartingOffset.QuadPart = 0;
dehydrationRange.Length.QuadPart = size; dehydrationRange.Length.QuadPart = size;
const qint64 result = CfUpdatePlaceholder(handle.get(), nullptr, const qint64 result = CfUpdatePlaceholder(handleForPath(path).get(), nullptr,
fileIdentity.data(), sizeToDWORD(fileIdentitySize), fileIdentity.data(), sizeToDWORD(fileIdentitySize),
&dehydrationRange, 1, CF_UPDATE_FLAG_MARK_IN_SYNC, nullptr, nullptr); &dehydrationRange, 1, CF_UPDATE_FLAG_MARK_IN_SYNC, nullptr, nullptr);
if (result != S_OK) { if (result != S_OK) {
qCWarning(lcCfApiWrapper) << "Couldn't update placeholder info for" << pathForHandle(handle) << ":" << QString::fromWCharArray(_com_error(result).ErrorMessage()); qCWarning(lcCfApiWrapper) << "Couldn't update placeholder info for" << path << ":" << QString::fromWCharArray(_com_error(result).ErrorMessage());
return { "Couldn't update placeholder info" }; return { "Couldn't update placeholder info" };
} }
return OCC::Vfs::ConvertToPlaceholderResult::Ok; return OCC::Vfs::ConvertToPlaceholderResult::Ok;
} }
OCC::Result<OCC::Vfs::ConvertToPlaceholderResult, QString> OCC::CfApiWrapper::convertToPlaceholder(const FileHandle &handle, time_t modtime, qint64 size, const QByteArray &fileId, const QString &replacesPath) OCC::Result<OCC::Vfs::ConvertToPlaceholderResult, QString> OCC::CfApiWrapper::convertToPlaceholder(const QString &path, time_t modtime, qint64 size, const QByteArray &fileId, const QString &replacesPath)
{ {
Q_UNUSED(modtime); Q_UNUSED(modtime);
Q_UNUSED(size); Q_UNUSED(size);
Q_ASSERT(handle);
const auto fileIdentity = QString::fromUtf8(fileId).toStdWString(); const auto fileIdentity = QString::fromUtf8(fileId).toStdWString();
const auto fileIdentitySize = (fileIdentity.length() + 1) * sizeof(wchar_t); const auto fileIdentitySize = (fileIdentity.length() + 1) * sizeof(wchar_t);
const qint64 result = CfConvertToPlaceholder(handle.get(), fileIdentity.data(), sizeToDWORD(fileIdentitySize), CF_CONVERT_FLAG_MARK_IN_SYNC, nullptr, nullptr); const qint64 result = CfConvertToPlaceholder(handleForPath(path).get(), fileIdentity.data(), sizeToDWORD(fileIdentitySize), CF_CONVERT_FLAG_MARK_IN_SYNC, nullptr, nullptr);
Q_ASSERT(result == S_OK); Q_ASSERT(result == S_OK);
if (result != S_OK) { if (result != S_OK) {
qCCritical(lcCfApiWrapper) << "Couldn't convert to placeholder" << pathForHandle(handle) << ":" << QString::fromWCharArray(_com_error(result).ErrorMessage()); qCCritical(lcCfApiWrapper) << "Couldn't convert to placeholder" << path << ":" << QString::fromWCharArray(_com_error(result).ErrorMessage());
return { "Couldn't convert to placeholder" }; return { "Couldn't convert to placeholder" };
} }
const auto originalHandle = handleForPath(replacesPath); const auto originalInfo = findPlaceholderInfo(replacesPath);
const auto originalInfo = originalHandle ? findPlaceholderInfo(originalHandle) : PlaceHolderInfo(nullptr, deletePlaceholderInfo);
if (!originalInfo) { if (!originalInfo) {
const auto stateResult = setPinState(handle, PinState::Inherited, NoRecurse); const auto stateResult = setPinState(path, PinState::Inherited, NoRecurse);
Q_ASSERT(stateResult); Q_ASSERT(stateResult);
return stateResult; return stateResult;
} else { } else {
const auto state = cfPinStateToPinState(originalInfo->PinState); const auto state = cfPinStateToPinState(originalInfo->PinState);
const auto stateResult = setPinState(handle, state, NoRecurse); const auto stateResult = setPinState(path, state, NoRecurse);
Q_ASSERT(stateResult); Q_ASSERT(stateResult);
return stateResult; return stateResult;
} }

View file

@ -84,7 +84,7 @@ NEXTCLOUD_CFAPI_EXPORT bool isSparseFile(const QString &path);
NEXTCLOUD_CFAPI_EXPORT FileHandle handleForPath(const QString &path); NEXTCLOUD_CFAPI_EXPORT FileHandle handleForPath(const QString &path);
PlaceHolderInfo findPlaceholderInfo(const FileHandle &handle); PlaceHolderInfo findPlaceholderInfo(const QString &path);
enum SetPinRecurseMode { enum SetPinRecurseMode {
NoRecurse = 0, NoRecurse = 0,
@ -92,11 +92,11 @@ enum SetPinRecurseMode {
ChildrenOnly ChildrenOnly
}; };
NEXTCLOUD_CFAPI_EXPORT Result<OCC::Vfs::ConvertToPlaceholderResult, QString> setPinState(const FileHandle &handle, PinState state, SetPinRecurseMode mode); NEXTCLOUD_CFAPI_EXPORT Result<OCC::Vfs::ConvertToPlaceholderResult, QString> setPinState(const QString &path, PinState state, SetPinRecurseMode mode);
NEXTCLOUD_CFAPI_EXPORT Result<void, QString> createPlaceholderInfo(const QString &path, time_t modtime, qint64 size, const QByteArray &fileId); NEXTCLOUD_CFAPI_EXPORT Result<void, QString> createPlaceholderInfo(const QString &path, time_t modtime, qint64 size, const QByteArray &fileId);
NEXTCLOUD_CFAPI_EXPORT Result<OCC::Vfs::ConvertToPlaceholderResult, QString> updatePlaceholderInfo(const FileHandle &handle, time_t modtime, qint64 size, const QByteArray &fileId, const QString &replacesPath = QString()); NEXTCLOUD_CFAPI_EXPORT Result<OCC::Vfs::ConvertToPlaceholderResult, QString> updatePlaceholderInfo(const QString &path, time_t modtime, qint64 size, const QByteArray &fileId, const QString &replacesPath = QString());
NEXTCLOUD_CFAPI_EXPORT Result<OCC::Vfs::ConvertToPlaceholderResult, QString> convertToPlaceholder(const FileHandle &handle, time_t modtime, qint64 size, const QByteArray &fileId, const QString &replacesPath); NEXTCLOUD_CFAPI_EXPORT Result<OCC::Vfs::ConvertToPlaceholderResult, QString> convertToPlaceholder(const QString &path, time_t modtime, qint64 size, const QByteArray &fileId, const QString &replacesPath);
NEXTCLOUD_CFAPI_EXPORT Result<OCC::Vfs::ConvertToPlaceholderResult, QString> dehydratePlaceholder(const FileHandle &handle, time_t modtime, qint64 size, const QByteArray &fileId); NEXTCLOUD_CFAPI_EXPORT Result<OCC::Vfs::ConvertToPlaceholderResult, QString> dehydratePlaceholder(const QString &path, time_t modtime, qint64 size, const QByteArray &fileId);
} }

View file

@ -172,9 +172,8 @@ bool VfsCfApi::isHydrating() const
Result<void, QString> VfsCfApi::updateMetadata(const QString &filePath, time_t modtime, qint64 size, const QByteArray &fileId) Result<void, QString> VfsCfApi::updateMetadata(const QString &filePath, time_t modtime, qint64 size, const QByteArray &fileId)
{ {
const auto localPath = QDir::toNativeSeparators(filePath); const auto localPath = QDir::toNativeSeparators(filePath);
const auto handle = cfapi::handleForPath(localPath); if (cfapi::handleForPath(localPath)) {
if (handle) { auto result = cfapi::updatePlaceholderInfo(localPath, modtime, size, fileId);
auto result = cfapi::updatePlaceholderInfo(handle, modtime, size, fileId);
if (result) { if (result) {
return {}; return {};
} else { } else {
@ -197,9 +196,8 @@ Result<void, QString> VfsCfApi::createPlaceholder(const SyncFileItem &item)
Result<void, QString> VfsCfApi::dehydratePlaceholder(const SyncFileItem &item) Result<void, QString> VfsCfApi::dehydratePlaceholder(const SyncFileItem &item)
{ {
const auto localPath = QDir::toNativeSeparators(_setupParams.filesystemPath + item._file); const auto localPath = QDir::toNativeSeparators(_setupParams.filesystemPath + item._file);
const auto handle = cfapi::handleForPath(localPath); if (cfapi::handleForPath(localPath)) {
if (handle) { auto result = cfapi::dehydratePlaceholder(localPath, item._modtime, item._size, item._fileId);
auto result = cfapi::dehydratePlaceholder(handle, item._modtime, item._size, item._fileId);
if (result) { if (result) {
return {}; return {};
} else { } else {
@ -216,14 +214,10 @@ Result<Vfs::ConvertToPlaceholderResult, QString> VfsCfApi::convertToPlaceholder(
const auto localPath = QDir::toNativeSeparators(filename); const auto localPath = QDir::toNativeSeparators(filename);
const auto replacesPath = QDir::toNativeSeparators(replacesFile); const auto replacesPath = QDir::toNativeSeparators(replacesFile);
const auto handle = cfapi::handleForPath(localPath); if (cfapi::findPlaceholderInfo(localPath)) {
if (!handle) { return cfapi::updatePlaceholderInfo(localPath, item._modtime, item._size, item._fileId, replacesPath);
return { "Invalid handle for path " + localPath };
}
if (cfapi::findPlaceholderInfo(handle)) {
return cfapi::updatePlaceholderInfo(handle, item._modtime, item._size, item._fileId, replacesPath);
} else { } else {
return cfapi::convertToPlaceholder(handle, item._modtime, item._size, item._fileId, replacesPath); return cfapi::convertToPlaceholder(localPath, item._modtime, item._size, item._fileId, replacesPath);
} }
} }
@ -278,29 +272,19 @@ bool VfsCfApi::statTypeVirtualFile(csync_file_stat_t *stat, void *statData)
bool VfsCfApi::setPinState(const QString &folderPath, PinState state) bool VfsCfApi::setPinState(const QString &folderPath, PinState state)
{ {
const auto localPath = QDir::toNativeSeparators(params().filesystemPath + folderPath); const auto localPath = QDir::toNativeSeparators(params().filesystemPath + folderPath);
const auto handle = cfapi::handleForPath(localPath);
if (handle) { if (cfapi::setPinState(localPath, state, cfapi::Recurse)) {
if (cfapi::setPinState(handle, state, cfapi::Recurse)) {
return true; return true;
} else { } else {
return false; return false;
} }
} else {
qCWarning(lcCfApi) << "Couldn't update pin state for non existing file" << localPath;
return false;
}
} }
Optional<PinState> VfsCfApi::pinState(const QString &folderPath) Optional<PinState> VfsCfApi::pinState(const QString &folderPath)
{ {
const auto localPath = QDir::toNativeSeparators(params().filesystemPath + folderPath); const auto localPath = QDir::toNativeSeparators(params().filesystemPath + folderPath);
const auto handle = cfapi::handleForPath(localPath);
if (!handle) {
qCWarning(lcCfApi) << "Couldn't find pin state for non existing file" << localPath;
return {};
}
const auto info = cfapi::findPlaceholderInfo(handle); const auto info = cfapi::findPlaceholderInfo(localPath);
if (!info) { if (!info) {
qCWarning(lcCfApi) << "Couldn't find pin state for regular non-placeholder file" << localPath; qCWarning(lcCfApi) << "Couldn't find pin state for regular non-placeholder file" << localPath;
return {}; return {};