master
cpp 122 lines 4.72 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 WslCoreFilesystem.cpp
8
9 Abstract:
10
11 This file contains filesystem helper function definitions.
12
13 --*/
14
15 #include "precomp.h"
16 #include "WslCoreFilesystem.h"
17 #include "WslSecurity.h"
18
19 wil::unique_hfile wsl::core::filesystem::CreateFile(
20 _In_ LPCWSTR fileName, _In_ DWORD desiredAccess, _In_ DWORD shareMode, _In_ DWORD creationDisposition, _In_ DWORD flagsAndAttributes, _In_ PSID userSid)
21 {
22 auto sd = windows::common::security::CreateSecurityDescriptor(userSid);
23 SECURITY_ATTRIBUTES sa{sizeof(SECURITY_ATTRIBUTES), &sd, false};
24 wil::unique_hfile file{CreateFileW(fileName, desiredAccess, shareMode, &sa, creationDisposition, flagsAndAttributes, nullptr)};
25 THROW_LAST_ERROR_IF(!file);
26
27 return file;
28 }
29
30 void wsl::core::filesystem::CreateVhd(_In_ LPCWSTR target, _In_ ULONGLONG maximumSize, _In_ PSID userSid, _In_ BOOL sparse, _In_ BOOL fixed)
31 {
32 THROW_HR_IF(
33 E_INVALIDARG,
34 !wsl::windows::common::string::IsPathComponentEqual(
35 std::filesystem::path{target}.extension().native(), windows::common::wslutil::c_vhdxFileExtension));
36
37 // Disable creation of sparse VHDs while data corruption is being debugged.
38 if (sparse)
39 {
40 sparse = false;
41 EMIT_USER_WARNING(wsl::shared::Localization::MessageSparseVhdDisabled());
42 }
43
44 VIRTUAL_STORAGE_TYPE storageType{};
45 storageType.DeviceId = VIRTUAL_STORAGE_TYPE_DEVICE_VHDX;
46 storageType.VendorId = VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT;
47
48 // Create a VHDX with the specified maximum size.
49 //
50 // N.B. The block size was chosen based on the best practices for Linux VHDs:
51 // https://docs.microsoft.com/en-us/windows-server/virtualization/hyper-v/best-practices-for-running-linux-on-hyper-v
52 CREATE_VIRTUAL_DISK_PARAMETERS createVhdParameters{};
53 createVhdParameters.Version = CREATE_VIRTUAL_DISK_VERSION_2;
54 createVhdParameters.Version2.BlockSizeInBytes = _1MB;
55 createVhdParameters.Version2.MaximumSize = maximumSize;
56
57 CREATE_VIRTUAL_DISK_FLAG flags = CREATE_VIRTUAL_DISK_FLAG_SUPPORT_COMPRESSED_VOLUMES;
58 WI_SetFlagIf(flags, CREATE_VIRTUAL_DISK_FLAG_FULL_PHYSICAL_ALLOCATION, fixed);
59 if (sparse)
60 {
61 WI_SetAllFlags(flags, CREATE_VIRTUAL_DISK_FLAG_SPARSE_FILE | CREATE_VIRTUAL_DISK_FLAG_SUPPORT_SPARSE_FILES_ANY_FS);
62 }
63
64 // Explicitly set the owner of the file so the default is not used.
65 //
66 // N.B. This ensures that HcsGrantVmAccess is able to add the required ACL
67 // to the VHD because the operation is done while impersonating the user.
68 auto sd = windows::common::security::CreateSecurityDescriptor(userSid);
69
70 wil::unique_hfile vhd{};
71 auto result = HRESULT_FROM_WIN32(
72 ::CreateVirtualDisk(&storageType, target, VIRTUAL_DISK_ACCESS_NONE, &sd, flags, 0, &createVhdParameters, nullptr, &vhd));
73 if (FAILED(result))
74 {
75 THROW_HR_WITH_USER_ERROR(
76 result, shared::Localization::MessageFailedToCreateDisk(target, windows::common::wslutil::GetErrorString(result)));
77 }
78 }
79
80 wil::unique_handle wsl::core::filesystem::OpenVhd(_In_ LPCWSTR Path, _In_ VIRTUAL_DISK_ACCESS_MASK Mask)
81 {
82 WI_ASSERT(wsl::windows::common::wslutil::IsVhdFile(std::filesystem::path{Path}));
83
84 // N.B. Specifying unknown for device and vendor means the system will determine the type of VHD.
85 VIRTUAL_STORAGE_TYPE storageType{};
86 storageType.DeviceId = VIRTUAL_STORAGE_TYPE_DEVICE_UNKNOWN;
87 storageType.VendorId = VIRTUAL_STORAGE_TYPE_VENDOR_UNKNOWN;
88
89 wil::unique_handle disk;
90 THROW_IF_WIN32_ERROR(OpenVirtualDisk(&storageType, Path, Mask, OPEN_VIRTUAL_DISK_FLAG_NONE, nullptr, &disk));
91
92 return disk;
93 }
94
95 void wsl::core::filesystem::CompactVhd(_In_ LPCWSTR Path)
96 {
97 auto diskHandle = OpenVhd(Path, VIRTUAL_DISK_ACCESS_GET_INFO | VIRTUAL_DISK_ACCESS_METAOPS);
98
99 COMPACT_VIRTUAL_DISK_PARAMETERS compact{};
100 compact.Version = COMPACT_VIRTUAL_DISK_VERSION_1;
101
102 THROW_IF_WIN32_ERROR(CompactVirtualDisk(diskHandle.get(), COMPACT_VIRTUAL_DISK_FLAG_NONE, &compact, nullptr));
103 }
104
105 void wsl::core::filesystem::ResizeExistingVhd(_In_ HANDLE diskHandle, _In_ ULONGLONG maximumSize, _In_ RESIZE_VIRTUAL_DISK_FLAG resizeFlag)
106 {
107 RESIZE_VIRTUAL_DISK_PARAMETERS resize{};
108 resize.Version1.NewSize = maximumSize;
109 resize.Version = RESIZE_VIRTUAL_DISK_VERSION_1;
110 THROW_IF_WIN32_ERROR(ResizeVirtualDisk(diskHandle, resizeFlag, &resize, nullptr));
111 }
112
113 ULONGLONG wsl::core::filesystem::GetDiskSize(_In_ HANDLE diskHandle)
114 {
115 GET_VIRTUAL_DISK_INFO virtualDiskInfo{};
116 virtualDiskInfo.Version = GET_VIRTUAL_DISK_INFO_SIZE;
117 ULONG size = sizeof(virtualDiskInfo);
118
119 THROW_IF_WIN32_ERROR(GetVirtualDiskInformation(diskHandle, &size, &virtualDiskInfo, nullptr));
120
121 return virtualDiskInfo.Size.VirtualSize;
122 }