3232# include <winioctl.h>
3333# include <lmcons.h> // UNLEN
3434# include "osdefs.h" // SEP
35+ # include <aclapi.h> // SetEntriesInAcl
36+ # include <sddl.h> // SDDL_REVISION_1
3537# if defined(MS_WINDOWS_DESKTOP ) || defined(MS_WINDOWS_SYSTEM )
3638# define HAVE_SYMLINK
3739# endif /* MS_WINDOWS_DESKTOP | MS_WINDOWS_SYSTEM */
@@ -5342,6 +5344,12 @@ os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
53425344/*[clinic end generated code: output=a70446903abe821f input=a61722e1576fab03]*/
53435345{
53445346 int result ;
5347+ #ifdef MS_WINDOWS
5348+ int error = 0 ;
5349+ int pathError = 0 ;
5350+ SECURITY_ATTRIBUTES secAttr = { sizeof (secAttr ) };
5351+ SECURITY_ATTRIBUTES * pSecAttr = NULL ;
5352+ #endif
53455353#ifdef HAVE_MKDIRAT
53465354 int mkdirat_unavailable = 0 ;
53475355#endif
@@ -5353,11 +5361,38 @@ os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
53535361
53545362#ifdef MS_WINDOWS
53555363 Py_BEGIN_ALLOW_THREADS
5356- result = CreateDirectoryW (path -> wide , NULL );
5364+ if (mode == 0700 /* 0o700 */ ) {
5365+ ULONG sdSize ;
5366+ pSecAttr = & secAttr ;
5367+ // Set a discreationary ACL (D) that is protected (P) and includes
5368+ // inheritable (OICI) entries that allow (A) full control (FA) to
5369+ // SYSTEM (SY), Administrators (BA), and the owner (OW).
5370+ if (!ConvertStringSecurityDescriptorToSecurityDescriptorW (
5371+ L"D:P(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FA;;;OW)" ,
5372+ SDDL_REVISION_1 ,
5373+ & secAttr .lpSecurityDescriptor ,
5374+ & sdSize
5375+ )) {
5376+ error = GetLastError ();
5377+ }
5378+ }
5379+ if (!error ) {
5380+ result = CreateDirectoryW (path -> wide , pSecAttr );
5381+ if (secAttr .lpSecurityDescriptor &&
5382+ // uncommonly, LocalFree returns non-zero on error, but still uses
5383+ // GetLastError() to see what the error code is
5384+ LocalFree (secAttr .lpSecurityDescriptor )) {
5385+ error = GetLastError ();
5386+ }
5387+ }
53575388 Py_END_ALLOW_THREADS
53585389
5359- if (!result )
5390+ if (error ) {
5391+ return PyErr_SetFromWindowsErr (error );
5392+ }
5393+ if (!result ) {
53605394 return path_error (path );
5395+ }
53615396#else
53625397 Py_BEGIN_ALLOW_THREADS
53635398#if HAVE_MKDIRAT
0 commit comments