diff --git a/packages/camera/camera_windows/CHANGELOG.md b/packages/camera/camera_windows/CHANGELOG.md index 56dd79f33fc..a7594047294 100644 --- a/packages/camera/camera_windows/CHANGELOG.md +++ b/packages/camera/camera_windows/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.2.6+6 + +* Falls back to the system temp directory for captured pictures and videos when + the Pictures / Videos known folder cannot be used, e.g. when blocked by + Controlled Folder Access. + ## 0.2.6+5 * Updates pigeon dev_dependency to ^27.3.2 for analyzer 14 compatibility. diff --git a/packages/camera/camera_windows/pubspec.yaml b/packages/camera/camera_windows/pubspec.yaml index a17da257bd4..aeea3eb8c9e 100644 --- a/packages/camera/camera_windows/pubspec.yaml +++ b/packages/camera/camera_windows/pubspec.yaml @@ -2,7 +2,7 @@ name: camera_windows description: A Flutter plugin for getting information about and controlling the camera on Windows. repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_windows issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 -version: 0.2.6+5 +version: 0.2.6+6 environment: sdk: ^3.10.0 diff --git a/packages/camera/camera_windows/windows/camera_plugin.cpp b/packages/camera/camera_windows/windows/camera_plugin.cpp index c01db2603ca..92fc1baaf4e 100644 --- a/packages/camera/camera_windows/windows/camera_plugin.cpp +++ b/packages/camera/camera_windows/windows/camera_plugin.cpp @@ -85,33 +85,48 @@ std::string GetCurrentTimeString() { return time_start + std::to_string(ms); } -// Builds file path for picture capture. -std::optional GetFilePathForPicture() { +// Returns the directory to write captures into. +// Falls back to the temp directory if the known folder can't be used, e.g. +// it's blocked by Controlled Folder Access. +std::optional GetCaptureDirectory(REFKNOWNFOLDERID folder_id) { ComHeapPtr known_folder_path; - HRESULT hr = SHGetKnownFolderPath(FOLDERID_Pictures, KF_FLAG_CREATE, nullptr, + // KF_FLAG_CREATE opens the folder with write intent even if it already + // exists, so this acts also as write permission check. + HRESULT hr = SHGetKnownFolderPath(folder_id, KF_FLAG_CREATE, nullptr, &known_folder_path); - if (FAILED(hr)) { + if (SUCCEEDED(hr)) { + return Utf8FromUtf16(std::wstring(known_folder_path)) + "\\"; + } + + wchar_t temp_path[MAX_PATH + 1]; + // The returned length includes the trailing backslash. + DWORD length = GetTempPathW(MAX_PATH + 1, temp_path); + if (length == 0 || length > MAX_PATH) { return std::nullopt; } - std::string path = Utf8FromUtf16(std::wstring(known_folder_path)); + return Utf8FromUtf16(std::wstring(temp_path, length)); +} - return path + "\\" + "PhotoCapture_" + GetCurrentTimeString() + "." + +// Builds file path for picture capture. +std::optional GetFilePathForPicture() { + std::optional directory = GetCaptureDirectory(FOLDERID_Pictures); + if (!directory) { + return std::nullopt; + } + + return *directory + "PhotoCapture_" + GetCurrentTimeString() + "." + kPictureCaptureExtension; } // Builds file path for video capture. std::optional GetFilePathForVideo() { - ComHeapPtr known_folder_path; - HRESULT hr = SHGetKnownFolderPath(FOLDERID_Videos, KF_FLAG_CREATE, nullptr, - &known_folder_path); - if (FAILED(hr)) { + std::optional directory = GetCaptureDirectory(FOLDERID_Videos); + if (!directory) { return std::nullopt; } - std::string path = Utf8FromUtf16(std::wstring(known_folder_path)); - - return path + "\\" + "VideoCapture_" + GetCurrentTimeString() + "." + + return *directory + "VideoCapture_" + GetCurrentTimeString() + "." + kVideoCaptureExtension; } } // namespace