@@ -677,4 +677,52 @@ mod _winapi {
677677
678678 Ok ( WinHandle ( handle) )
679679 }
680+
681+ /// Helper for GetShortPathName and GetLongPathName
682+ fn get_path_name_impl (
683+ path : & PyStrRef ,
684+ api_fn : unsafe extern "system" fn ( * const u16 , * mut u16 , u32 ) -> u32 ,
685+ vm : & VirtualMachine ,
686+ ) -> PyResult < PyStrRef > {
687+ use rustpython_common:: wtf8:: Wtf8Buf ;
688+
689+ let path_wide = path. as_wtf8 ( ) . to_wide_with_nul ( ) ;
690+
691+ // First call to get required buffer size
692+ let size = unsafe { api_fn ( path_wide. as_ptr ( ) , null_mut ( ) , 0 ) } ;
693+
694+ if size == 0 {
695+ return Err ( vm. new_last_os_error ( ) ) ;
696+ }
697+
698+ // Second call to get the actual path
699+ let mut buffer: Vec < u16 > = vec ! [ 0 ; size as usize ] ;
700+ let result =
701+ unsafe { api_fn ( path_wide. as_ptr ( ) , buffer. as_mut_ptr ( ) , buffer. len ( ) as u32 ) } ;
702+
703+ if result == 0 {
704+ return Err ( vm. new_last_os_error ( ) ) ;
705+ }
706+
707+ // Truncate to actual length (excluding null terminator)
708+ buffer. truncate ( result as usize ) ;
709+
710+ // Convert UTF-16 back to WTF-8 (handles surrogates properly)
711+ let result_str = Wtf8Buf :: from_wide ( & buffer) ;
712+ Ok ( vm. ctx . new_str ( result_str) )
713+ }
714+
715+ /// GetShortPathName - Return the short version of the provided path.
716+ #[ pyfunction]
717+ fn GetShortPathName ( path : PyStrRef , vm : & VirtualMachine ) -> PyResult < PyStrRef > {
718+ use windows_sys:: Win32 :: Storage :: FileSystem :: GetShortPathNameW ;
719+ get_path_name_impl ( & path, GetShortPathNameW , vm)
720+ }
721+
722+ /// GetLongPathName - Return the long version of the provided path.
723+ #[ pyfunction]
724+ fn GetLongPathName ( path : PyStrRef , vm : & VirtualMachine ) -> PyResult < PyStrRef > {
725+ use windows_sys:: Win32 :: Storage :: FileSystem :: GetLongPathNameW ;
726+ get_path_name_impl ( & path, GetLongPathNameW , vm)
727+ }
680728}
0 commit comments