@@ -692,18 +692,59 @@ pub(crate) mod module {
692692 raw_set_handle_inheritable ( handle, inheritable) . map_err ( |e| e. to_pyexception ( vm) )
693693 }
694694
695- #[ pyfunction]
696- fn mkdir (
695+ #[ derive( FromArgs ) ]
696+ struct MkdirArgs < ' a > {
697+ #[ pyarg( any) ]
697698 path : OsPath ,
698- mode : OptionalArg < i32 > ,
699- dir_fd : DirFd < ' _ , { _os:: MKDIR_DIR_FD as usize } > ,
700- vm : & VirtualMachine ,
701- ) -> PyResult < ( ) > {
702- let mode = mode. unwrap_or ( 0o777 ) ;
703- let [ ] = dir_fd. 0 ;
704- let _ = mode;
705- let wide = path. to_wide_cstring ( vm) ?;
706- let res = unsafe { FileSystem :: CreateDirectoryW ( wide. as_ptr ( ) , std:: ptr:: null_mut ( ) ) } ;
699+ #[ pyarg( any, default = 0o777 ) ]
700+ mode : i32 ,
701+ #[ pyarg( flatten) ]
702+ dir_fd : DirFd < ' a , { _os:: MKDIR_DIR_FD as usize } > ,
703+ }
704+
705+ #[ pyfunction]
706+ fn mkdir ( args : MkdirArgs < ' _ > , vm : & VirtualMachine ) -> PyResult < ( ) > {
707+ use windows_sys:: Win32 :: Foundation :: LocalFree ;
708+ use windows_sys:: Win32 :: Security :: Authorization :: {
709+ ConvertStringSecurityDescriptorToSecurityDescriptorW , SDDL_REVISION_1 ,
710+ } ;
711+ use windows_sys:: Win32 :: Security :: SECURITY_ATTRIBUTES ;
712+
713+ let [ ] = args. dir_fd . 0 ;
714+ let wide = args. path . to_wide_cstring ( vm) ?;
715+
716+ // CPython special case: mode 0o700 sets a protected ACL
717+ let res = if args. mode == 0o700 {
718+ let mut sec_attr = SECURITY_ATTRIBUTES {
719+ nLength : std:: mem:: size_of :: < SECURITY_ATTRIBUTES > ( ) as u32 ,
720+ lpSecurityDescriptor : std:: ptr:: null_mut ( ) ,
721+ bInheritHandle : 0 ,
722+ } ;
723+ // Set a discretionary ACL (D) that is protected (P) and includes
724+ // inheritable (OICI) entries that allow (A) full control (FA) to
725+ // SYSTEM (SY), Administrators (BA), and the owner (OW).
726+ let sddl: Vec < u16 > = "D:P(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FA;;;OW)\0 "
727+ . encode_utf16 ( )
728+ . collect ( ) ;
729+ let convert_result = unsafe {
730+ ConvertStringSecurityDescriptorToSecurityDescriptorW (
731+ sddl. as_ptr ( ) ,
732+ SDDL_REVISION_1 ,
733+ & mut sec_attr. lpSecurityDescriptor ,
734+ std:: ptr:: null_mut ( ) ,
735+ )
736+ } ;
737+ if convert_result == 0 {
738+ return Err ( errno_err ( vm) ) ;
739+ }
740+ let res =
741+ unsafe { FileSystem :: CreateDirectoryW ( wide. as_ptr ( ) , & sec_attr as * const _ as _ ) } ;
742+ unsafe { LocalFree ( sec_attr. lpSecurityDescriptor ) } ;
743+ res
744+ } else {
745+ unsafe { FileSystem :: CreateDirectoryW ( wide. as_ptr ( ) , std:: ptr:: null_mut ( ) ) }
746+ } ;
747+
707748 if res == 0 {
708749 return Err ( errno_err ( vm) ) ;
709750 }
0 commit comments