-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathPlanceholders.cpp
More file actions
105 lines (87 loc) · 2.98 KB
/
Planceholders.cpp
File metadata and controls
105 lines (87 loc) · 2.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include <stdafx.h>
#include <Placeholders.h>
#include <winrt/base.h>
#include <shlwapi.h>
#include <vector>
#include <filesystem>
#include <fstream>
#include <random>
#include <iostream>
#include <Utilities.h>
#include <winbase.h>
#include <string>
#include <cctype>
#include <windows.h>
#include <shlobj.h>
#include <convert_to_placeholder.h>
#include <check_hresult.h>
winrt::file_handle Placeholders::OpenFileHandle(const std::wstring &path, DWORD dwDesiredAccess, bool openAsPlaceholder)
{
bool isDirectory = std::filesystem::is_directory(path);
DWORD dwFlagsAndAttributes = 0;
if (openAsPlaceholder)
dwFlagsAndAttributes |= FILE_FLAG_OPEN_REPARSE_POINT;
if (isDirectory)
dwFlagsAndAttributes |= FILE_FLAG_BACKUP_SEMANTICS;
DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
winrt::file_handle fileHandle{CreateFileW(
path.c_str(),
dwDesiredAccess,
dwShareMode,
nullptr,
OPEN_EXISTING,
dwFlagsAndAttributes,
nullptr)};
if (!fileHandle)
{
throw std::runtime_error("Failed to open file handle: " + std::to_string(GetLastError()));
}
return fileHandle;
}
void Placeholders::UpdateSyncStatus(const std::wstring &path)
{
auto fileHandle = Placeholders::OpenFileHandle(path, FILE_WRITE_ATTRIBUTES, true);
check_hresult(
"CfSetInSyncState",
CfSetInSyncState(
fileHandle.get(),
CF_IN_SYNC_STATE_IN_SYNC,
CF_SET_IN_SYNC_FLAG_NONE,
nullptr));
SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATH, path.c_str(), nullptr);
}
void Placeholders::UpdateFileIdentity(const std::wstring &path, const std::wstring &placeholderId)
{
auto fileHandle = OpenFileHandle(path, FILE_WRITE_ATTRIBUTES, true);
check_hresult(
"CfUpdatePlaceholder",
CfUpdatePlaceholder(
fileHandle.get(),
nullptr,
placeholderId.c_str(),
static_cast<DWORD>(placeholderId.size() * sizeof(wchar_t)),
nullptr,
0,
CF_UPDATE_FLAG_NONE,
nullptr,
nullptr));
}
FileState Placeholders::GetPlaceholderInfo(const std::wstring &path)
{
auto fileHandle = OpenFileHandle(path, FILE_READ_ATTRIBUTES, true);
constexpr DWORD fileIdMaxLength = 400;
constexpr DWORD infoSize = sizeof(CF_PLACEHOLDER_BASIC_INFO) + fileIdMaxLength;
std::vector<char> buffer(infoSize);
auto *info = reinterpret_cast<CF_PLACEHOLDER_BASIC_INFO *>(buffer.data());
check_hresult(
"CfGetPlaceholderInfo",
CfGetPlaceholderInfo(
fileHandle.get(),
CF_PLACEHOLDER_INFO_BASIC,
info,
infoSize,
nullptr));
std::string placeholderId(reinterpret_cast<const char *>(info->FileIdentity), info->FileIdentityLength);
placeholderId.erase(std::remove(placeholderId.begin(), placeholderId.end(), '\0'), placeholderId.end());
return FileState{placeholderId, info->PinState};
}