(path: OsPath, vm: &VirtualMachine)
| 2156 | /// returns the substitute name from reparse data which includes the prefix |
| 2157 | #[pyfunction] |
| 2158 | fn readlink(path: OsPath, vm: &VirtualMachine) -> PyResult { |
| 2159 | use crate::common::windows::ToWideString; |
| 2160 | use windows_sys::Win32::Foundation::CloseHandle; |
| 2161 | use windows_sys::Win32::Storage::FileSystem::{ |
| 2162 | CreateFileW, FILE_FLAG_BACKUP_SEMANTICS, FILE_FLAG_OPEN_REPARSE_POINT, |
| 2163 | FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE, OPEN_EXISTING, |
| 2164 | }; |
| 2165 | use windows_sys::Win32::System::IO::DeviceIoControl; |
| 2166 | use windows_sys::Win32::System::Ioctl::FSCTL_GET_REPARSE_POINT; |
| 2167 | |
| 2168 | let mode = path.mode(); |
| 2169 | let wide_path = path.as_ref().to_wide_with_nul(); |
| 2170 | |
| 2171 | // Open the file/directory with reparse point flag |
| 2172 | let handle = unsafe { |
| 2173 | CreateFileW( |
| 2174 | wide_path.as_ptr(), |
| 2175 | 0, // No access needed, just reading reparse data |
| 2176 | FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, |
| 2177 | core::ptr::null(), |
| 2178 | OPEN_EXISTING, |
| 2179 | FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, |
| 2180 | core::ptr::null_mut(), |
| 2181 | ) |
| 2182 | }; |
| 2183 | |
| 2184 | if handle == INVALID_HANDLE_VALUE { |
| 2185 | return Err(OSErrorBuilder::with_filename( |
| 2186 | &io::Error::last_os_error(), |
| 2187 | path.clone(), |
| 2188 | vm, |
| 2189 | )); |
| 2190 | } |
| 2191 | |
| 2192 | // Buffer for reparse data - MAXIMUM_REPARSE_DATA_BUFFER_SIZE is 16384 |
| 2193 | const BUFFER_SIZE: usize = 16384; |
| 2194 | let mut buffer = vec![0u8; BUFFER_SIZE]; |
| 2195 | let mut bytes_returned: u32 = 0; |
| 2196 | |
| 2197 | let result = unsafe { |
| 2198 | DeviceIoControl( |
| 2199 | handle, |
| 2200 | FSCTL_GET_REPARSE_POINT, |
| 2201 | core::ptr::null(), |
| 2202 | 0, |
| 2203 | buffer.as_mut_ptr() as *mut _, |
| 2204 | BUFFER_SIZE as u32, |
| 2205 | &mut bytes_returned, |
| 2206 | core::ptr::null_mut(), |
| 2207 | ) |
| 2208 | }; |
| 2209 | |
| 2210 | unsafe { CloseHandle(handle) }; |
| 2211 | |
| 2212 | if result == 0 { |
| 2213 | return Err(OSErrorBuilder::with_filename( |
| 2214 | &io::Error::last_os_error(), |
| 2215 | path.clone(), |
no test coverage detected