@@ -790,18 +790,59 @@ pub(crate) mod module {
790790 raw_set_handle_inheritable ( handle, inheritable) . map_err ( |e| e. to_pyexception ( vm) )
791791 }
792792
793- #[ pyfunction]
794- fn mkdir (
793+ #[ derive( FromArgs ) ]
794+ struct MkdirArgs < ' a > {
795+ #[ pyarg( any) ]
795796 path : OsPath ,
796- mode : OptionalArg < i32 > ,
797- dir_fd : DirFd < ' _ , { _os:: MKDIR_DIR_FD as usize } > ,
798- vm : & VirtualMachine ,
799- ) -> PyResult < ( ) > {
800- let mode = mode. unwrap_or ( 0o777 ) ;
801- let [ ] = dir_fd. 0 ;
802- let _ = mode;
803- let wide = path. to_wide_cstring ( vm) ?;
804- let res = unsafe { FileSystem :: CreateDirectoryW ( wide. as_ptr ( ) , std:: ptr:: null_mut ( ) ) } ;
797+ #[ pyarg( any, default = 0o777 ) ]
798+ mode : i32 ,
799+ #[ pyarg( flatten) ]
800+ dir_fd : DirFd < ' a , { _os:: MKDIR_DIR_FD as usize } > ,
801+ }
802+
803+ #[ pyfunction]
804+ fn mkdir ( args : MkdirArgs < ' _ > , vm : & VirtualMachine ) -> PyResult < ( ) > {
805+ use windows_sys:: Win32 :: Foundation :: LocalFree ;
806+ use windows_sys:: Win32 :: Security :: Authorization :: {
807+ ConvertStringSecurityDescriptorToSecurityDescriptorW , SDDL_REVISION_1 ,
808+ } ;
809+ use windows_sys:: Win32 :: Security :: SECURITY_ATTRIBUTES ;
810+
811+ let [ ] = args. dir_fd . 0 ;
812+ let wide = args. path . to_wide_cstring ( vm) ?;
813+
814+ // CPython special case: mode 0o700 sets a protected ACL
815+ let res = if args. mode == 0o700 {
816+ let mut sec_attr = SECURITY_ATTRIBUTES {
817+ nLength : std:: mem:: size_of :: < SECURITY_ATTRIBUTES > ( ) as u32 ,
818+ lpSecurityDescriptor : std:: ptr:: null_mut ( ) ,
819+ bInheritHandle : 0 ,
820+ } ;
821+ // Set a discretionary ACL (D) that is protected (P) and includes
822+ // inheritable (OICI) entries that allow (A) full control (FA) to
823+ // SYSTEM (SY), Administrators (BA), and the owner (OW).
824+ let sddl: Vec < u16 > = "D:P(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FA;;;OW)\0 "
825+ . encode_utf16 ( )
826+ . collect ( ) ;
827+ let convert_result = unsafe {
828+ ConvertStringSecurityDescriptorToSecurityDescriptorW (
829+ sddl. as_ptr ( ) ,
830+ SDDL_REVISION_1 ,
831+ & mut sec_attr. lpSecurityDescriptor ,
832+ std:: ptr:: null_mut ( ) ,
833+ )
834+ } ;
835+ if convert_result == 0 {
836+ return Err ( errno_err ( vm) ) ;
837+ }
838+ let res =
839+ unsafe { FileSystem :: CreateDirectoryW ( wide. as_ptr ( ) , & sec_attr as * const _ as _ ) } ;
840+ unsafe { LocalFree ( sec_attr. lpSecurityDescriptor ) } ;
841+ res
842+ } else {
843+ unsafe { FileSystem :: CreateDirectoryW ( wide. as_ptr ( ) , std:: ptr:: null_mut ( ) ) }
844+ } ;
845+
805846 if res == 0 {
806847 return Err ( errno_err ( vm) ) ;
807848 }
0 commit comments