@@ -682,6 +682,87 @@ pub(crate) mod module {
682682 Ok ( vm. ctx . new_list ( drives) )
683683 }
684684
685+ #[ pyfunction]
686+ fn listvolumes ( vm : & VirtualMachine ) -> PyResult < PyListRef > {
687+ use windows_sys:: Win32 :: Foundation :: ERROR_NO_MORE_FILES ;
688+
689+ let mut result = Vec :: new ( ) ;
690+ let mut buffer = [ 0u16 ; Foundation :: MAX_PATH as usize + 1 ] ;
691+
692+ let find = unsafe { FileSystem :: FindFirstVolumeW ( buffer. as_mut_ptr ( ) , buffer. len ( ) as _ ) } ;
693+ if find == INVALID_HANDLE_VALUE {
694+ return Err ( errno_err ( vm) ) ;
695+ }
696+
697+ loop {
698+ // Find the null terminator
699+ let len = buffer. iter ( ) . position ( |& c| c == 0 ) . unwrap_or ( buffer. len ( ) ) ;
700+ let volume = String :: from_utf16_lossy ( & buffer[ ..len] ) ;
701+ result. push ( vm. new_pyobj ( volume) ) ;
702+
703+ let ret = unsafe {
704+ FileSystem :: FindNextVolumeW ( find, buffer. as_mut_ptr ( ) , buffer. len ( ) as _ )
705+ } ;
706+ if ret == 0 {
707+ let err = io:: Error :: last_os_error ( ) ;
708+ unsafe { FileSystem :: FindVolumeClose ( find) } ;
709+ if err. raw_os_error ( ) == Some ( ERROR_NO_MORE_FILES as i32 ) {
710+ break ;
711+ }
712+ return Err ( err. to_pyexception ( vm) ) ;
713+ }
714+ }
715+
716+ Ok ( vm. ctx . new_list ( result) )
717+ }
718+
719+ #[ pyfunction]
720+ fn listmounts ( volume : OsPath , vm : & VirtualMachine ) -> PyResult < PyListRef > {
721+ use windows_sys:: Win32 :: Foundation :: ERROR_MORE_DATA ;
722+
723+ let wide = volume. to_wide_cstring ( vm) ?;
724+ let mut buflen: u32 = Foundation :: MAX_PATH + 1 ;
725+ let mut buffer: Vec < u16 > = vec ! [ 0 ; buflen as usize ] ;
726+
727+ loop {
728+ let success = unsafe {
729+ FileSystem :: GetVolumePathNamesForVolumeNameW (
730+ wide. as_ptr ( ) ,
731+ buffer. as_mut_ptr ( ) ,
732+ buflen,
733+ & mut buflen,
734+ )
735+ } ;
736+ if success != 0 {
737+ break ;
738+ }
739+ let err = io:: Error :: last_os_error ( ) ;
740+ if err. raw_os_error ( ) == Some ( ERROR_MORE_DATA as i32 ) {
741+ buffer. resize ( buflen as usize , 0 ) ;
742+ continue ;
743+ }
744+ return Err ( err. to_pyexception ( vm) ) ;
745+ }
746+
747+ // Parse null-separated strings
748+ let mut result = Vec :: new ( ) ;
749+ let mut start = 0 ;
750+ for ( i, & c) in buffer. iter ( ) . enumerate ( ) {
751+ if c == 0 {
752+ if i > start {
753+ let mount = String :: from_utf16_lossy ( & buffer[ start..i] ) ;
754+ result. push ( vm. new_pyobj ( mount) ) ;
755+ }
756+ start = i + 1 ;
757+ if start < buffer. len ( ) && buffer[ start] == 0 {
758+ break ; // Double null = end
759+ }
760+ }
761+ }
762+
763+ Ok ( vm. ctx . new_list ( result) )
764+ }
765+
685766 #[ pyfunction]
686767 fn set_handle_inheritable (
687768 handle : intptr_t ,
0 commit comments