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