| 818 | // WriteFile |
| 819 | #[pymethod] |
| 820 | fn WriteFile( |
| 821 | zelf: &Py<Self>, |
| 822 | handle: isize, |
| 823 | buf: PyBuffer, |
| 824 | vm: &VirtualMachine, |
| 825 | ) -> PyResult { |
| 826 | use windows_sys::Win32::Foundation::{ERROR_IO_PENDING, ERROR_SUCCESS}; |
| 827 | use windows_sys::Win32::Storage::FileSystem::WriteFile; |
| 828 | |
| 829 | let mut inner = zelf.inner.lock(); |
| 830 | if !matches!(inner.data, OverlappedData::None) { |
| 831 | return Err(vm.new_value_error("operation already attempted")); |
| 832 | } |
| 833 | |
| 834 | inner.handle = handle as HANDLE; |
| 835 | let buf_len = buf.desc.len; |
| 836 | if buf_len > u32::MAX as usize { |
| 837 | return Err(vm.new_value_error("buffer too large")); |
| 838 | } |
| 839 | |
| 840 | // For async write, buffer must be contiguous - we can't use a temporary copy |
| 841 | // because Windows reads from the buffer after this call returns |
| 842 | let Some(contiguous) = buf.as_contiguous() else { |
| 843 | return Err(vm.new_buffer_error("buffer is not contiguous")); |
| 844 | }; |
| 845 | |
| 846 | inner.data = OverlappedData::Write(buf.clone()); |
| 847 | |
| 848 | let mut written: u32 = 0; |
| 849 | let ret = unsafe { |
| 850 | WriteFile( |
| 851 | handle as HANDLE, |
| 852 | contiguous.as_ptr() as *const _, |
| 853 | buf_len as u32, |
| 854 | &mut written, |
| 855 | &mut inner.overlapped, |
| 856 | ) |
| 857 | }; |
| 858 | |
| 859 | let err = if ret != 0 { |
| 860 | ERROR_SUCCESS |
| 861 | } else { |
| 862 | unsafe { GetLastError() } |
| 863 | }; |
| 864 | inner.error = err; |
| 865 | |
| 866 | match err { |
| 867 | ERROR_SUCCESS | ERROR_IO_PENDING => Ok(vm.ctx.none()), |
| 868 | _ => { |
| 869 | inner.data = OverlappedData::NotStarted; |
| 870 | Err(set_from_windows_err(err, vm)) |
| 871 | } |
| 872 | } |
| 873 | } |
| 874 | |
| 875 | // WSASend |
| 876 | #[pymethod] |