From b6c50975ea8453f8a9378aecfc452ac8c3e904d9 Mon Sep 17 00:00:00 2001 From: LLFBandit Date: Fri, 4 Sep 2026 15:10:26 +0200 Subject: [PATCH 1/2] [camera_windows] Fall back to temp dir for capture path. --- packages/camera/camera_windows/CHANGELOG.md | 5 +++ packages/camera/camera_windows/pubspec.yaml | 2 +- .../camera_windows/windows/camera_plugin.cpp | 39 ++++++++++++------- 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/packages/camera/camera_windows/CHANGELOG.md b/packages/camera/camera_windows/CHANGELOG.md index 56dd79f33fce..24a3304d89a2 100644 --- a/packages/camera/camera_windows/CHANGELOG.md +++ b/packages/camera/camera_windows/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.2.6+6 + +* Falls back to the system temp directory for captured pictures and videos when + the Pictures / Videos known folder cannot be resolved. + ## 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 a17da257bd42..aeea3eb8c9e9 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 c01db2603caa..1552f4adca2c 100644 --- a/packages/camera/camera_windows/windows/camera_plugin.cpp +++ b/packages/camera/camera_windows/windows/camera_plugin.cpp @@ -85,33 +85,46 @@ 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 redirected or blocked by controlled folder access. +std::optional GetCaptureDirectory(REFKNOWNFOLDERID folder_id) { ComHeapPtr known_folder_path; - HRESULT hr = SHGetKnownFolderPath(FOLDERID_Pictures, KF_FLAG_CREATE, nullptr, + 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 From ce6fa5e96b845d53f9c04cc71700d24833a4fd11 Mon Sep 17 00:00:00 2001 From: LLFBandit Date: Sat, 5 Sep 2026 01:26:42 +0200 Subject: [PATCH 2/2] [camera_windows] Refine comments on fall back to temp dir for capture path. --- packages/camera/camera_windows/CHANGELOG.md | 3 ++- packages/camera/camera_windows/windows/camera_plugin.cpp | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/camera/camera_windows/CHANGELOG.md b/packages/camera/camera_windows/CHANGELOG.md index 24a3304d89a2..a75940472944 100644 --- a/packages/camera/camera_windows/CHANGELOG.md +++ b/packages/camera/camera_windows/CHANGELOG.md @@ -1,7 +1,8 @@ ## 0.2.6+6 * Falls back to the system temp directory for captured pictures and videos when - the Pictures / Videos known folder cannot be resolved. + the Pictures / Videos known folder cannot be used, e.g. when blocked by + Controlled Folder Access. ## 0.2.6+5 diff --git a/packages/camera/camera_windows/windows/camera_plugin.cpp b/packages/camera/camera_windows/windows/camera_plugin.cpp index 1552f4adca2c..92fc1baaf4ea 100644 --- a/packages/camera/camera_windows/windows/camera_plugin.cpp +++ b/packages/camera/camera_windows/windows/camera_plugin.cpp @@ -87,9 +87,11 @@ std::string GetCurrentTimeString() { // 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 redirected or blocked by controlled folder access. +// it's blocked by Controlled Folder Access. std::optional GetCaptureDirectory(REFKNOWNFOLDERID folder_id) { ComHeapPtr known_folder_path; + // 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 (SUCCEEDED(hr)) {