Backed out changeset: 17df50df62c7
This commit is contained in:
parent
15efd2b643
commit
fbf963c064
|
@ -39,10 +39,6 @@ try:
|
||||||
import fcntl
|
import fcntl
|
||||||
except ImportError:
|
except ImportError:
|
||||||
fcntl = None
|
fcntl = None
|
||||||
try:
|
|
||||||
import _winapi
|
|
||||||
except ImportError:
|
|
||||||
_winapi = None
|
|
||||||
|
|
||||||
from test.script_helper import assert_python_ok
|
from test.script_helper import assert_python_ok
|
||||||
|
|
||||||
|
@ -1777,37 +1773,6 @@ class Win32SymlinkTests(unittest.TestCase):
|
||||||
shutil.rmtree(level1)
|
shutil.rmtree(level1)
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
|
|
||||||
class Win32JunctionTests(unittest.TestCase):
|
|
||||||
junction = 'junctiontest'
|
|
||||||
junction_target = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
assert os.path.exists(self.junction_target)
|
|
||||||
assert not os.path.exists(self.junction)
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
if os.path.exists(self.junction):
|
|
||||||
# os.rmdir delegates to Windows' RemoveDirectoryW,
|
|
||||||
# which removes junction points safely.
|
|
||||||
os.rmdir(self.junction)
|
|
||||||
|
|
||||||
def test_create_junction(self):
|
|
||||||
_winapi.CreateJunction(self.junction_target, self.junction)
|
|
||||||
self.assertTrue(os.path.exists(self.junction))
|
|
||||||
self.assertTrue(os.path.isdir(self.junction))
|
|
||||||
|
|
||||||
# Junctions are not recognized as links.
|
|
||||||
self.assertFalse(os.path.islink(self.junction))
|
|
||||||
|
|
||||||
def test_unlink_removes_junction(self):
|
|
||||||
_winapi.CreateJunction(self.junction_target, self.junction)
|
|
||||||
self.assertTrue(os.path.exists(self.junction))
|
|
||||||
|
|
||||||
os.unlink(self.junction)
|
|
||||||
self.assertFalse(os.path.exists(self.junction))
|
|
||||||
|
|
||||||
|
|
||||||
@support.skip_unless_symlink
|
@support.skip_unless_symlink
|
||||||
class NonLocalSymlinkTests(unittest.TestCase):
|
class NonLocalSymlinkTests(unittest.TestCase):
|
||||||
|
|
||||||
|
@ -2579,7 +2544,6 @@ def test_main():
|
||||||
RemoveDirsTests,
|
RemoveDirsTests,
|
||||||
CPUCountTests,
|
CPUCountTests,
|
||||||
FDInheritanceTests,
|
FDInheritanceTests,
|
||||||
Win32JunctionTests,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -468,7 +468,6 @@ Chris Gonnerman
|
||||||
Shelley Gooch
|
Shelley Gooch
|
||||||
David Goodger
|
David Goodger
|
||||||
Hans de Graaff
|
Hans de Graaff
|
||||||
Kim Gräsman
|
|
||||||
Nathaniel Gray
|
Nathaniel Gray
|
||||||
Eddy De Greef
|
Eddy De Greef
|
||||||
Grant Griffin
|
Grant Griffin
|
||||||
|
|
|
@ -40,7 +40,6 @@
|
||||||
#define WINDOWS_LEAN_AND_MEAN
|
#define WINDOWS_LEAN_AND_MEAN
|
||||||
#include "windows.h"
|
#include "windows.h"
|
||||||
#include <crtdbg.h>
|
#include <crtdbg.h>
|
||||||
#include "winreparse.h"
|
|
||||||
|
|
||||||
#if defined(MS_WIN32) && !defined(MS_WIN64)
|
#if defined(MS_WIN32) && !defined(MS_WIN64)
|
||||||
#define HANDLE_TO_PYNUM(handle) \
|
#define HANDLE_TO_PYNUM(handle) \
|
||||||
|
@ -401,112 +400,6 @@ winapi_CreateFile(PyObject *self, PyObject *args)
|
||||||
return Py_BuildValue(F_HANDLE, handle);
|
return Py_BuildValue(F_HANDLE, handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
winapi_CreateJunction(PyObject *self, PyObject *args)
|
|
||||||
{
|
|
||||||
/* Input arguments */
|
|
||||||
LPWSTR src_path = NULL;
|
|
||||||
LPWSTR dst_path = NULL;
|
|
||||||
|
|
||||||
/* Privilege adjustment */
|
|
||||||
HANDLE token = NULL;
|
|
||||||
TOKEN_PRIVILEGES tp;
|
|
||||||
|
|
||||||
/* Reparse data buffer */
|
|
||||||
const USHORT prefix_len = 4;
|
|
||||||
USHORT print_len = 0;
|
|
||||||
USHORT rdb_size = 0;
|
|
||||||
PREPARSE_DATA_BUFFER rdb = NULL;
|
|
||||||
|
|
||||||
/* Junction point creation */
|
|
||||||
HANDLE junction = NULL;
|
|
||||||
DWORD ret = 0;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "uu",
|
|
||||||
&src_path, &dst_path))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (memcmp(src_path, L"\\??\\", prefix_len * sizeof(WCHAR)) == 0)
|
|
||||||
return PyErr_SetFromWindowsErr(ERROR_INVALID_PARAMETER);
|
|
||||||
|
|
||||||
/* Adjust privileges to allow rewriting directory entry as a
|
|
||||||
junction point. */
|
|
||||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
if (!LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &tp.Privileges[0].Luid))
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
tp.PrivilegeCount = 1;
|
|
||||||
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
|
||||||
if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES),
|
|
||||||
NULL, NULL))
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
if (GetFileAttributesW(src_path) == INVALID_FILE_ATTRIBUTES)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
print_len = (USHORT)GetFullPathNameW(src_path, 0, NULL, NULL);
|
|
||||||
if (print_len == 0)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
/* NUL terminator should not be part of print_len */
|
|
||||||
--print_len;
|
|
||||||
|
|
||||||
rdb_size = REPARSE_DATA_BUFFER_HEADER_SIZE +
|
|
||||||
sizeof(rdb->MountPointReparseBuffer) -
|
|
||||||
sizeof(rdb->MountPointReparseBuffer.PathBuffer) +
|
|
||||||
/* Two +1's for NUL terminators. */
|
|
||||||
(prefix_len + print_len + 1 + print_len + 1) * sizeof(WCHAR);
|
|
||||||
rdb = (PREPARSE_DATA_BUFFER)PyMem_RawMalloc(rdb_size, 1);
|
|
||||||
|
|
||||||
rdb->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
|
|
||||||
rdb->ReparseDataLength = rdb_size - REPARSE_DATA_BUFFER_HEADER_SIZE;
|
|
||||||
rdb->MountPointReparseBuffer.SubstituteNameOffset = 0;
|
|
||||||
rdb->MountPointReparseBuffer.SubstituteNameLength =
|
|
||||||
(prefix_len + print_len) * sizeof(WCHAR);
|
|
||||||
rdb->MountPointReparseBuffer.PrintNameOffset =
|
|
||||||
rdb->MountPointReparseBuffer.SubstituteNameLength + sizeof(WCHAR);
|
|
||||||
rdb->MountPointReparseBuffer.PrintNameLength = print_len * sizeof(WCHAR);
|
|
||||||
|
|
||||||
lstrcpyW(rdb->MountPointReparseBuffer.PathBuffer, L"\\??\\");
|
|
||||||
if (GetFullPathNameW(src_path, print_len + 1,
|
|
||||||
rdb->MountPointReparseBuffer.PathBuffer + prefix_len,
|
|
||||||
NULL) == 0)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
lstrcpyW(rdb->MountPointReparseBuffer.PathBuffer +
|
|
||||||
prefix_len + print_len + 1,
|
|
||||||
rdb->MountPointReparseBuffer.PathBuffer + prefix_len);
|
|
||||||
|
|
||||||
/* Create a directory for the junction point. */
|
|
||||||
if (!CreateDirectoryW(dst_path, NULL))
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
junction = CreateFileW(dst_path, GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
|
||||||
OPEN_EXISTING,
|
|
||||||
FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
|
||||||
if (junction == INVALID_HANDLE_VALUE)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
/* Make the directory entry a junction point. */
|
|
||||||
if (!DeviceIoControl(junction, FSCTL_SET_REPARSE_POINT, rdb, rdb_size,
|
|
||||||
NULL, 0, &ret, NULL))
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
ret = GetLastError();
|
|
||||||
|
|
||||||
CloseHandle(token);
|
|
||||||
CloseHandle(junction);
|
|
||||||
free(rdb);
|
|
||||||
|
|
||||||
if (ret != 0)
|
|
||||||
return PyErr_SetFromWindowsErr(ret);
|
|
||||||
|
|
||||||
Py_RETURN_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
winapi_CreateNamedPipe(PyObject *self, PyObject *args)
|
winapi_CreateNamedPipe(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
|
@ -1332,8 +1225,6 @@ static PyMethodDef winapi_functions[] = {
|
||||||
METH_VARARGS | METH_KEYWORDS, ""},
|
METH_VARARGS | METH_KEYWORDS, ""},
|
||||||
{"CreateFile", winapi_CreateFile, METH_VARARGS,
|
{"CreateFile", winapi_CreateFile, METH_VARARGS,
|
||||||
""},
|
""},
|
||||||
{"CreateJunction", winapi_CreateJunction, METH_VARARGS,
|
|
||||||
""},
|
|
||||||
{"CreateNamedPipe", winapi_CreateNamedPipe, METH_VARARGS,
|
{"CreateNamedPipe", winapi_CreateNamedPipe, METH_VARARGS,
|
||||||
""},
|
""},
|
||||||
{"CreatePipe", winapi_CreatePipe, METH_VARARGS,
|
{"CreatePipe", winapi_CreatePipe, METH_VARARGS,
|
||||||
|
|
|
@ -27,8 +27,6 @@
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#ifndef MS_WINDOWS
|
#ifndef MS_WINDOWS
|
||||||
#include "posixmodule.h"
|
#include "posixmodule.h"
|
||||||
#else
|
|
||||||
#include "winreparse.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -303,9 +301,6 @@ extern int lstat(const char *, struct stat *);
|
||||||
#ifndef IO_REPARSE_TAG_SYMLINK
|
#ifndef IO_REPARSE_TAG_SYMLINK
|
||||||
#define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
|
#define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
|
||||||
#endif
|
#endif
|
||||||
#ifndef IO_REPARSE_TAG_MOUNT_POINT
|
|
||||||
#define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L)
|
|
||||||
#endif
|
|
||||||
#include "osdefs.h"
|
#include "osdefs.h"
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
@ -1114,6 +1109,41 @@ _PyVerify_fd_dup2(int fd1, int fd2)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
|
/* The following structure was copied from
|
||||||
|
http://msdn.microsoft.com/en-us/library/ms791514.aspx as the required
|
||||||
|
include doesn't seem to be present in the Windows SDK (at least as included
|
||||||
|
with Visual Studio Express). */
|
||||||
|
typedef struct _REPARSE_DATA_BUFFER {
|
||||||
|
ULONG ReparseTag;
|
||||||
|
USHORT ReparseDataLength;
|
||||||
|
USHORT Reserved;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
USHORT SubstituteNameOffset;
|
||||||
|
USHORT SubstituteNameLength;
|
||||||
|
USHORT PrintNameOffset;
|
||||||
|
USHORT PrintNameLength;
|
||||||
|
ULONG Flags;
|
||||||
|
WCHAR PathBuffer[1];
|
||||||
|
} SymbolicLinkReparseBuffer;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
USHORT SubstituteNameOffset;
|
||||||
|
USHORT SubstituteNameLength;
|
||||||
|
USHORT PrintNameOffset;
|
||||||
|
USHORT PrintNameLength;
|
||||||
|
WCHAR PathBuffer[1];
|
||||||
|
} MountPointReparseBuffer;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
UCHAR DataBuffer[1];
|
||||||
|
} GenericReparseBuffer;
|
||||||
|
};
|
||||||
|
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
|
||||||
|
|
||||||
|
#define REPARSE_DATA_BUFFER_HEADER_SIZE FIELD_OFFSET(REPARSE_DATA_BUFFER,\
|
||||||
|
GenericReparseBuffer)
|
||||||
|
#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE ( 16 * 1024 )
|
||||||
|
|
||||||
static int
|
static int
|
||||||
win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag)
|
win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag)
|
||||||
|
@ -4462,10 +4492,7 @@ BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
|
||||||
find_data_handle = FindFirstFileW(lpFileName, &find_data);
|
find_data_handle = FindFirstFileW(lpFileName, &find_data);
|
||||||
|
|
||||||
if(find_data_handle != INVALID_HANDLE_VALUE) {
|
if(find_data_handle != INVALID_HANDLE_VALUE) {
|
||||||
/* IO_REPARSE_TAG_SYMLINK if it is a symlink and
|
is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK;
|
||||||
IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
|
|
||||||
is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
|
|
||||||
find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
|
|
||||||
FindClose(find_data_handle);
|
FindClose(find_data_handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,53 +0,0 @@
|
||||||
#ifndef Py_WINREPARSE_H
|
|
||||||
#define Py_WINREPARSE_H
|
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
|
||||||
#include <Windows.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* The following structure was copied from
|
|
||||||
http://msdn.microsoft.com/en-us/library/ff552012.aspx as the required
|
|
||||||
include doesn't seem to be present in the Windows SDK (at least as included
|
|
||||||
with Visual Studio Express). */
|
|
||||||
typedef struct _REPARSE_DATA_BUFFER {
|
|
||||||
ULONG ReparseTag;
|
|
||||||
USHORT ReparseDataLength;
|
|
||||||
USHORT Reserved;
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
USHORT SubstituteNameOffset;
|
|
||||||
USHORT SubstituteNameLength;
|
|
||||||
USHORT PrintNameOffset;
|
|
||||||
USHORT PrintNameLength;
|
|
||||||
ULONG Flags;
|
|
||||||
WCHAR PathBuffer[1];
|
|
||||||
} SymbolicLinkReparseBuffer;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
USHORT SubstituteNameOffset;
|
|
||||||
USHORT SubstituteNameLength;
|
|
||||||
USHORT PrintNameOffset;
|
|
||||||
USHORT PrintNameLength;
|
|
||||||
WCHAR PathBuffer[1];
|
|
||||||
} MountPointReparseBuffer;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
UCHAR DataBuffer[1];
|
|
||||||
} GenericReparseBuffer;
|
|
||||||
};
|
|
||||||
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
|
|
||||||
|
|
||||||
#define REPARSE_DATA_BUFFER_HEADER_SIZE FIELD_OFFSET(REPARSE_DATA_BUFFER,\
|
|
||||||
GenericReparseBuffer)
|
|
||||||
#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE ( 16 * 1024 )
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* MS_WINDOWS */
|
|
||||||
|
|
||||||
#endif /* !Py_WINREPARSE_H */
|
|
Loading…
Reference in New Issue