Skip to content

Commit dc26511

Browse files
committed
COM APIs
1 parent d0f487c commit dc26511

File tree

1 file changed

+34
-13
lines changed

1 file changed

+34
-13
lines changed

dev/Interop/StoragePickers/PickerCommon.cpp

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22
#include "PickerCommon.h"
33
#include <wil/resource.h>
44
#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>
511
#include <KnownFolders.h>
612

713
namespace {
@@ -122,30 +128,45 @@ namespace PickerCommon {
122128
return value.empty();
123129
}
124130

125-
126131
// TODO: better way to convert ShellItem a StorageFile without relying on path?.
127132
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Storage::StorageFile> CreateStorageFileFromShellItem(winrt::com_ptr<IShellItem> shellItem)
128133
{
129134
wil::unique_cotaskmem_string filePath;
130135
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));
131142

132143
co_await winrt::resume_background();
133144

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))
141146
{
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();
144157

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;
148167
}
168+
169+
co_return co_await winrt::Windows::Storage::StorageFile::GetFileFromPathAsync(pathStr);
149170
}
150171

151172
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Storage::StorageFolder> CreateStorageFolderFromShellItem(winrt::com_ptr<IShellItem> shellItem)

0 commit comments

Comments
 (0)