|
2 | 2 | #include "PickerCommon.h"
|
3 | 3 | #include <wil/resource.h>
|
4 | 4 | #include "ShObjIdl.h"
|
| 5 | +#include <shlobj.h> |
| 6 | +#include <shlwapi.h> |
| 7 | +#include <shobjidl_core.h> |
| 8 | +#include <atlbase.h> |
| 9 | +#include <string> |
| 10 | +#include <winrt/base.h> |
5 | 11 | #include <KnownFolders.h>
|
6 | 12 |
|
7 | 13 | namespace {
|
@@ -122,30 +128,45 @@ namespace PickerCommon {
|
122 | 128 | return value.empty();
|
123 | 129 | }
|
124 | 130 |
|
125 |
| - |
126 | 131 | // TODO: better way to convert ShellItem a StorageFile without relying on path?.
|
127 | 132 | winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Storage::StorageFile> CreateStorageFileFromShellItem(winrt::com_ptr<IShellItem> shellItem)
|
128 | 133 | {
|
129 | 134 | wil::unique_cotaskmem_string filePath;
|
130 | 135 | check_hresult(shellItem->GetDisplayName(SIGDN_FILESYSPATH, &filePath));
|
| 136 | + auto pathStr = filePath.get(); |
| 137 | + |
| 138 | + // Check ShellItem attributes to see if it's an actual file on disk |
| 139 | + SFGAOF desiredAttributes = SFGAO_FILESYSTEM | SFGAO_STREAM; |
| 140 | + SFGAOF shellItemAttributes = 0; |
| 141 | + check_hresult(shellItem->GetAttributes(desiredAttributes, &shellItemAttributes)); |
131 | 142 |
|
132 | 143 | co_await winrt::resume_background();
|
133 | 144 |
|
134 |
| - auto pathStr = filePath.get(); |
135 |
| - std::error_code ec; |
136 |
| - if (std::filesystem::exists(pathStr, ec)) |
137 |
| - { |
138 |
| - co_return co_await winrt::Windows::Storage::StorageFile::GetFileFromPathAsync(pathStr); |
139 |
| - } |
140 |
| - else |
| 145 | + if (!(shellItemAttributes & SFGAO_FILESYSTEM) || !(shellItemAttributes & SFGAO_STREAM)) |
141 | 146 | {
|
142 |
| - auto folderPath = std::filesystem::path(pathStr).parent_path().wstring(); |
143 |
| - auto fileName = std::filesystem::path(pathStr).filename().wstring(); |
| 147 | + winrt::com_ptr<IShellItem> pParentFolder; |
| 148 | + check_hresult(shellItem->GetParent(pParentFolder.put())); |
| 149 | + |
| 150 | + winrt::com_ptr<IShellFolder> pShellFolder; |
| 151 | + check_hresult(pParentFolder->BindToHandler(nullptr, BHID_SFObject, IID_PPV_ARGS(pShellFolder.put()))); |
| 152 | + |
| 153 | + // Get the file name. |
| 154 | + wil::unique_cotaskmem_string fileNameObj; |
| 155 | + check_hresult(shellItem->GetDisplayName(SIGDN_NORMALDISPLAY, &fileNameObj)); |
| 156 | + auto fileName = fileNameObj.get(); |
144 | 157 |
|
145 |
| - // Open the parent folder and create the file if it doesn't exist |
146 |
| - auto folder = co_await winrt::Windows::Storage::StorageFolder::GetFolderFromPathAsync(folderPath); |
147 |
| - co_return co_await folder.CreateFileAsync(fileName, winrt::Windows::Storage::CreationCollisionOption::OpenIfExists); |
| 158 | + // The file doesn't exist, create file. |
| 159 | + winrt::com_ptr<IStorage> pStorage; |
| 160 | + check_hresult(pShellFolder->CreateViewObject(NULL, IID_PPV_ARGS(&pStorage))); |
| 161 | + |
| 162 | + winrt::com_ptr<IStream> pStream; |
| 163 | + check_hresult(pStorage->CreateStream(fileName, STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, pStream.put())); |
| 164 | + |
| 165 | + // Close the stream to finalize the file creation |
| 166 | + pStream = nullptr; |
148 | 167 | }
|
| 168 | + |
| 169 | + co_return co_await winrt::Windows::Storage::StorageFile::GetFileFromPathAsync(pathStr); |
149 | 170 | }
|
150 | 171 |
|
151 | 172 | winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Storage::StorageFolder> CreateStorageFolderFromShellItem(winrt::com_ptr<IShellItem> shellItem)
|
|
0 commit comments