32
32
# include <winioctl.h>
33
33
# include <lmcons.h> // UNLEN
34
34
# include "osdefs.h" // SEP
35
+ # include <aclapi.h> // SetEntriesInAcl
36
+ # include <sddl.h> // SDDL_REVISION_1
35
37
# if defined(MS_WINDOWS_DESKTOP ) || defined(MS_WINDOWS_SYSTEM )
36
38
# define HAVE_SYMLINK
37
39
# endif /* MS_WINDOWS_DESKTOP | MS_WINDOWS_SYSTEM */
@@ -5342,6 +5344,12 @@ os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
5342
5344
/*[clinic end generated code: output=a70446903abe821f input=a61722e1576fab03]*/
5343
5345
{
5344
5346
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
5345
5353
#ifdef HAVE_MKDIRAT
5346
5354
int mkdirat_unavailable = 0 ;
5347
5355
#endif
@@ -5353,11 +5361,38 @@ os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
5353
5361
5354
5362
#ifdef MS_WINDOWS
5355
5363
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
+ }
5357
5388
Py_END_ALLOW_THREADS
5358
5389
5359
- if (!result )
5390
+ if (error ) {
5391
+ return PyErr_SetFromWindowsErr (error );
5392
+ }
5393
+ if (!result ) {
5360
5394
return path_error (path );
5395
+ }
5361
5396
#else
5362
5397
Py_BEGIN_ALLOW_THREADS
5363
5398
#if HAVE_MKDIRAT
0 commit comments