6#if defined(DART_HOST_OS_WINDOWS)
32PathBuffer::~PathBuffer() {
36char* PathBuffer::AsString()
const {
41wchar_t* PathBuffer::AsStringW()
const {
42 return reinterpret_cast<wchar_t*
>(data_);
45const char* PathBuffer::AsScopedString()
const {
46 return StringUtilsWin::WideToUtf8(AsStringW());
49bool PathBuffer::Add(
const char*
name) {
51 return AddW(wide_name.get());
54bool PathBuffer::AddW(
const wchar_t*
name) {
55 wchar_t*
data = AsStringW();
71 AsStringW()[length_] =
L'\0';
76static bool IsBrokenLink(
const wchar_t* link_name) {
77 HANDLE handle = CreateFileW(
78 link_name, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
79 nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,
nullptr);
98static bool DeleteRecursively(PathBuffer*
path);
100static ListType HandleFindFile(DirectoryListing* listing,
101 DirectoryListingEntry* entry,
102 const WIN32_FIND_DATAW& find_file_data) {
103 if (!listing->path_buffer().AddW(find_file_data.cFileName)) {
106 DWORD attributes = find_file_data.dwFileAttributes;
107 if ((attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
108 if (!listing->follow_links()) {
111 HANDLE handle = CreateFileW(
112 listing->path_buffer().AsStringW(), 0,
113 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr,
114 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,
nullptr);
119 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
121 LinkList current_link;
122 BY_HANDLE_FILE_INFORMATION
info;
124 if (!GetFileInformationByHandle(handle, &
info)) {
131 current_link.volume =
info.dwVolumeSerialNumber;
132 current_link.id_low =
info.nFileIndexLow;
133 current_link.id_high =
info.nFileIndexHigh;
134 current_link.next = entry->link();
135 LinkList* previous = entry->link();
136 while (previous !=
nullptr) {
137 if ((previous->volume == current_link.volume) &&
138 (previous->id_low == current_link.id_low) &&
139 (previous->id_high == current_link.id_high)) {
143 previous = previous->next;
146 if ((wcscmp(find_file_data.cFileName,
L".") == 0) ||
147 (wcscmp(find_file_data.cFileName,
L"..") == 0)) {
148 return entry->Next(listing);
150 entry->set_link(
new LinkList(current_link));
154 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
155 if ((wcscmp(find_file_data.cFileName,
L".") == 0) ||
156 (wcscmp(find_file_data.cFileName,
L"..") == 0)) {
157 return entry->Next(listing);
165ListType DirectoryListingEntry::Next(DirectoryListing* listing) {
170 WIN32_FIND_DATAW find_file_data;
173 const wchar_t*
tail = parent_ ==
nullptr ?
L"*" :
L"\\*";
174 if (!listing->path_buffer().AddW(
tail)) {
179 path_length_ = listing->path_buffer().length() - 1;
182 FindFirstFileW(listing->path_buffer().AsStringW(), &find_file_data);
189 lister_ =
reinterpret_cast<intptr_t
>(find_handle);
191 listing->path_buffer().Reset(path_length_);
193 return HandleFindFile(listing,
this, find_file_data);
197 listing->path_buffer().Reset(path_length_);
200 if (FindNextFileW(
reinterpret_cast<HANDLE>(lister_), &find_file_data) != 0) {
201 return HandleFindFile(listing,
this, find_file_data);
213DirectoryListingEntry::~DirectoryListingEntry() {
216 FindClose(
reinterpret_cast<HANDLE>(lister_));
220void DirectoryListingEntry::ResetLink() {
221 if ((link_ !=
nullptr) &&
222 ((parent_ ==
nullptr) || (parent_->link_ != link_))) {
226 if (parent_ !=
nullptr) {
227 link_ = parent_->link_;
232class RecursiveDeleter {
234 RecursiveDeleter() : path_() {}
239 bool DeleteRecursively(
const std::unique_ptr<
wchar_t[]>&
path) {
242 if (
path ==
nullptr || !path_.AddW(
path.get()) || path_.length() == 0) {
246 if (path_.AsStringW()[path_.length() - 1] ==
'\\') {
248 path_.Reset(path_.length() - 1);
251 return DeleteDirectory();
255 const wchar_t*
path()
const {
return path_.AsStringW(); }
257 bool DeleteDirectory() {
258 DWORD attributes = GetFileAttributesW(
path());
259 if (attributes == INVALID_FILE_ATTRIBUTES) {
265 if ((attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
267 return RemoveDirectoryW(
path()) != 0;
271 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
275 if (!path_.AddW(
L"\\*")) {
279 WIN32_FIND_DATAW find_file_data;
280 HANDLE find_handle = FindFirstFileW(
path(), &find_file_data);
287 const int path_length = path_.length() - 1;
288 path_.Reset(path_length);
291 if (!DeleteEntry(&find_file_data)) {
294 path_.Reset(path_length);
295 }
while (FindNextFileW(find_handle, &find_file_data) != 0);
299 FindClose(find_handle);
300 if (last_error != ERROR_NO_MORE_FILES) {
307 path_.Reset(path_length - 1);
308 return RemoveDirectoryW(
path()) != 0;
311 bool DeleteEntry(LPWIN32_FIND_DATAW find_file_data) {
312 wchar_t* entry_name = find_file_data->cFileName;
313 if ((wcscmp(entry_name,
L".") == 0) || (wcscmp(entry_name,
L"..") == 0)) {
317 if (!path_.AddW(entry_name)) {
321 DWORD attributes = find_file_data->dwFileAttributes;
322 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
323 return DeleteDirectory();
330 if (DeleteFileW(
path()) != 0) {
338 DWORD attributes = GetFileAttributesW(
path());
339 if (attributes == INVALID_FILE_ATTRIBUTES) {
343 if ((attributes & FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY) {
344 attributes &= ~FILE_ATTRIBUTE_READONLY;
346 if (SetFileAttributesW(
path(), attributes) == 0) {
350 return DeleteFileW(
path()) != 0;
361Directory::ExistsResult Directory::Exists(
const wchar_t* dir_name) {
362 DWORD attributes = GetFileAttributesW(dir_name);
363 if (attributes == INVALID_FILE_ATTRIBUTES) {
366 (last_error == ERROR_PATH_NOT_FOUND)) {
367 return Directory::DOES_NOT_EXIST;
372 return Directory::UNKNOWN;
375 bool exists = (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
376 exists = exists && !IsBrokenLink(dir_name);
377 return exists ? Directory::EXISTS : Directory::DOES_NOT_EXIST;
380Directory::ExistsResult Directory::Exists(Namespace* namespc,
381 const char* dir_name) {
383 return Exists(
path.get());
386char* Directory::CurrentNoScope() {
387 int length = GetCurrentDirectoryW(0,
nullptr);
391 wchar_t* current =
new wchar_t[
length + 1];
392 GetCurrentDirectoryW(
length + 1, current);
393 int utf8_len = WideCharToMultiByte(CP_UTF8, 0, current, -1,
nullptr, 0,
395 char*
result =
reinterpret_cast<char*
>(
malloc(utf8_len));
396 WideCharToMultiByte(CP_UTF8, 0, current, -1,
result, utf8_len,
nullptr,
404 int create_status = CreateDirectoryW(
path.get(),
nullptr);
406 if ((create_status == 0) && (
GetLastError() == ERROR_ALREADY_EXISTS) &&
407 (Exists(
path.get()) == EXISTS)) {
410 return (create_status != 0);
413const char* Directory::SystemTemp(Namespace* namespc) {
417 return path.AsScopedString();
421static const char* CreateTempFromUUID(
const char*
prefix) {
424 if (!
path.AddW(system_prefix.get())) {
434 RPC_STATUS status = UuidCreateSequential(&uuid);
435 if ((status != RPC_S_OK) && (status != RPC_S_UUID_LOCAL_ONLY)) {
438 wchar_t* uuid_string;
439 status = UuidToStringW(&uuid, &uuid_string);
440 if (status != RPC_S_OK) {
445 if (!
path.AddW(uuid_string)) {
448 RpcStringFreeW(&uuid_string);
449 if (!CreateDirectoryW(
path.AsStringW(),
nullptr)) {
452 return path.AsScopedString();
467const char* Directory::CreateTemp(Namespace* namespc,
const char*
prefix) {
470 if (!
path.AddW(system_prefix.get())) {
482 uint32_t suffix_bytes = 0;
483 const int kSuffixSize =
sizeof(suffix_bytes);
484 if (!Crypto::GetRandomBytes(kSuffixSize,
485 reinterpret_cast<uint8_t*
>(&suffix_bytes))) {
487 return CreateTempFromUUID(
prefix);
491 char suffix[kSuffixSize * 2 + 1];
492 Utils::SNPrint(
suffix,
sizeof(
suffix),
"%x", suffix_bytes);
498 if (!CreateDirectoryW(
path.AsStringW(),
nullptr)) {
501 return CreateTempFromUUID(
prefix);
503 return path.AsScopedString();
506bool Directory::Delete(Namespace* namespc,
507 const char* dir_name,
514 File::kIsDirectory) {
520 RecursiveDeleter deleter;
526bool Directory::Rename(Namespace* namespc,
527 const char* old_name,
528 const char* new_name) {
530 ExistsResult exists = Exists(old_path.get());
531 if (exists != EXISTS) {
537 int move_status = MoveFileExW(old_path.get(), new_path.get(),
flags);
538 return (move_status != 0);
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
static float next(float f)
static sk_sp< Effect > Create()
FlutterSemanticsFlag flags
const uint8_t uint32_t uint32_t GError ** error
std::unique_ptr< wchar_t[]> Utf8ToWideChar(const char *path)
std::unique_ptr< wchar_t[]> ToWinAPIDirectoryPath(const char *path, bool force_long_prefix=false)
void * malloc(size_t size)
void * calloc(size_t n, size_t size)
static Dart_TypedData_Type GetType(intptr_t class_id)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
DEF_SWITCHES_START aot vmservice shared library name
std::shared_ptr< const fml::Mapping > data
#define INVALID_HANDLE_VALUE
WINBASEAPI VOID WINAPI SetLastError(_In_ DWORD dwErrCode)
WINBASEAPI _Check_return_ _Post_equals_last_error_ DWORD WINAPI GetLastError(VOID)
#define ERROR_FILE_NOT_FOUND
#define ERROR_ACCESS_DENIED