mirror of
https://github.com/clinton-hall/nzbToMedia.git
synced 2024-11-14 17:40:24 -08:00
323 lines
9.7 KiB
Python
323 lines
9.7 KiB
Python
import ctypes.wintypes
|
|
|
|
CreateSymbolicLink = ctypes.windll.kernel32.CreateSymbolicLinkW
|
|
CreateSymbolicLink.argtypes = (
|
|
ctypes.wintypes.LPWSTR,
|
|
ctypes.wintypes.LPWSTR,
|
|
ctypes.wintypes.DWORD,
|
|
)
|
|
CreateSymbolicLink.restype = ctypes.wintypes.BOOLEAN
|
|
|
|
SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE = 0x2
|
|
|
|
CreateHardLink = ctypes.windll.kernel32.CreateHardLinkW
|
|
CreateHardLink.argtypes = (
|
|
ctypes.wintypes.LPWSTR,
|
|
ctypes.wintypes.LPWSTR,
|
|
ctypes.wintypes.LPVOID, # reserved for LPSECURITY_ATTRIBUTES
|
|
)
|
|
CreateHardLink.restype = ctypes.wintypes.BOOLEAN
|
|
|
|
GetFileAttributes = ctypes.windll.kernel32.GetFileAttributesW
|
|
GetFileAttributes.argtypes = (ctypes.wintypes.LPWSTR,)
|
|
GetFileAttributes.restype = ctypes.wintypes.DWORD
|
|
|
|
SetFileAttributes = ctypes.windll.kernel32.SetFileAttributesW
|
|
SetFileAttributes.argtypes = ctypes.wintypes.LPWSTR, ctypes.wintypes.DWORD
|
|
SetFileAttributes.restype = ctypes.wintypes.BOOL
|
|
|
|
MAX_PATH = 260
|
|
|
|
GetFinalPathNameByHandle = ctypes.windll.kernel32.GetFinalPathNameByHandleW
|
|
GetFinalPathNameByHandle.argtypes = (
|
|
ctypes.wintypes.HANDLE,
|
|
ctypes.wintypes.LPWSTR,
|
|
ctypes.wintypes.DWORD,
|
|
ctypes.wintypes.DWORD,
|
|
)
|
|
GetFinalPathNameByHandle.restype = ctypes.wintypes.DWORD
|
|
|
|
|
|
class SECURITY_ATTRIBUTES(ctypes.Structure):
|
|
_fields_ = (
|
|
('length', ctypes.wintypes.DWORD),
|
|
('p_security_descriptor', ctypes.wintypes.LPVOID),
|
|
('inherit_handle', ctypes.wintypes.BOOLEAN),
|
|
)
|
|
|
|
|
|
LPSECURITY_ATTRIBUTES = ctypes.POINTER(SECURITY_ATTRIBUTES)
|
|
|
|
CreateFile = ctypes.windll.kernel32.CreateFileW
|
|
CreateFile.argtypes = (
|
|
ctypes.wintypes.LPWSTR,
|
|
ctypes.wintypes.DWORD,
|
|
ctypes.wintypes.DWORD,
|
|
LPSECURITY_ATTRIBUTES,
|
|
ctypes.wintypes.DWORD,
|
|
ctypes.wintypes.DWORD,
|
|
ctypes.wintypes.HANDLE,
|
|
)
|
|
CreateFile.restype = ctypes.wintypes.HANDLE
|
|
FILE_SHARE_READ = 1
|
|
FILE_SHARE_WRITE = 2
|
|
FILE_SHARE_DELETE = 4
|
|
FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000
|
|
FILE_FLAG_BACKUP_SEMANTICS = 0x2000000
|
|
NULL = 0
|
|
OPEN_EXISTING = 3
|
|
FILE_ATTRIBUTE_READONLY = 0x1
|
|
FILE_ATTRIBUTE_HIDDEN = 0x2
|
|
FILE_ATTRIBUTE_DIRECTORY = 0x10
|
|
FILE_ATTRIBUTE_NORMAL = 0x80
|
|
FILE_ATTRIBUTE_REPARSE_POINT = 0x400
|
|
GENERIC_READ = 0x80000000
|
|
FILE_READ_ATTRIBUTES = 0x80
|
|
INVALID_HANDLE_VALUE = ctypes.wintypes.HANDLE(-1).value
|
|
|
|
INVALID_FILE_ATTRIBUTES = 0xFFFFFFFF
|
|
|
|
ERROR_NO_MORE_FILES = 0x12
|
|
|
|
VOLUME_NAME_DOS = 0
|
|
|
|
CloseHandle = ctypes.windll.kernel32.CloseHandle
|
|
CloseHandle.argtypes = (ctypes.wintypes.HANDLE,)
|
|
CloseHandle.restype = ctypes.wintypes.BOOLEAN
|
|
|
|
|
|
class WIN32_FIND_DATA(ctypes.wintypes.WIN32_FIND_DATAW):
|
|
"""
|
|
_fields_ = [
|
|
("dwFileAttributes", DWORD),
|
|
("ftCreationTime", FILETIME),
|
|
("ftLastAccessTime", FILETIME),
|
|
("ftLastWriteTime", FILETIME),
|
|
("nFileSizeHigh", DWORD),
|
|
("nFileSizeLow", DWORD),
|
|
("dwReserved0", DWORD),
|
|
("dwReserved1", DWORD),
|
|
("cFileName", WCHAR * MAX_PATH),
|
|
("cAlternateFileName", WCHAR * 14)]
|
|
]
|
|
"""
|
|
|
|
@property
|
|
def file_attributes(self):
|
|
return self.dwFileAttributes
|
|
|
|
@property
|
|
def creation_time(self):
|
|
return self.ftCreationTime
|
|
|
|
@property
|
|
def last_access_time(self):
|
|
return self.ftLastAccessTime
|
|
|
|
@property
|
|
def last_write_time(self):
|
|
return self.ftLastWriteTime
|
|
|
|
@property
|
|
def file_size_words(self):
|
|
return [self.nFileSizeHigh, self.nFileSizeLow]
|
|
|
|
@property
|
|
def reserved(self):
|
|
return [self.dwReserved0, self.dwReserved1]
|
|
|
|
@property
|
|
def filename(self):
|
|
return self.cFileName
|
|
|
|
@property
|
|
def alternate_filename(self):
|
|
return self.cAlternateFileName
|
|
|
|
@property
|
|
def file_size(self):
|
|
return self.nFileSizeHigh << 32 + self.nFileSizeLow
|
|
|
|
|
|
LPWIN32_FIND_DATA = ctypes.POINTER(ctypes.wintypes.WIN32_FIND_DATAW)
|
|
|
|
FindFirstFile = ctypes.windll.kernel32.FindFirstFileW
|
|
FindFirstFile.argtypes = (ctypes.wintypes.LPWSTR, LPWIN32_FIND_DATA)
|
|
FindFirstFile.restype = ctypes.wintypes.HANDLE
|
|
FindNextFile = ctypes.windll.kernel32.FindNextFileW
|
|
FindNextFile.argtypes = (ctypes.wintypes.HANDLE, LPWIN32_FIND_DATA)
|
|
FindNextFile.restype = ctypes.wintypes.BOOLEAN
|
|
|
|
ctypes.windll.kernel32.FindClose.argtypes = (ctypes.wintypes.HANDLE,)
|
|
|
|
SCS_32BIT_BINARY = 0 # A 32-bit Windows-based application
|
|
SCS_64BIT_BINARY = 6 # A 64-bit Windows-based application
|
|
SCS_DOS_BINARY = 1 # An MS-DOS-based application
|
|
SCS_OS216_BINARY = 5 # A 16-bit OS/2-based application
|
|
SCS_PIF_BINARY = 3 # A PIF file that executes an MS-DOS-based application
|
|
SCS_POSIX_BINARY = 4 # A POSIX-based application
|
|
SCS_WOW_BINARY = 2 # A 16-bit Windows-based application
|
|
|
|
_GetBinaryType = ctypes.windll.kernel32.GetBinaryTypeW
|
|
_GetBinaryType.argtypes = (
|
|
ctypes.wintypes.LPWSTR,
|
|
ctypes.POINTER(ctypes.wintypes.DWORD),
|
|
)
|
|
_GetBinaryType.restype = ctypes.wintypes.BOOL
|
|
|
|
FILEOP_FLAGS = ctypes.wintypes.WORD
|
|
|
|
|
|
class BY_HANDLE_FILE_INFORMATION(ctypes.Structure):
|
|
_fields_ = [
|
|
('file_attributes', ctypes.wintypes.DWORD),
|
|
('creation_time', ctypes.wintypes.FILETIME),
|
|
('last_access_time', ctypes.wintypes.FILETIME),
|
|
('last_write_time', ctypes.wintypes.FILETIME),
|
|
('volume_serial_number', ctypes.wintypes.DWORD),
|
|
('file_size_high', ctypes.wintypes.DWORD),
|
|
('file_size_low', ctypes.wintypes.DWORD),
|
|
('number_of_links', ctypes.wintypes.DWORD),
|
|
('file_index_high', ctypes.wintypes.DWORD),
|
|
('file_index_low', ctypes.wintypes.DWORD),
|
|
]
|
|
|
|
@property
|
|
def file_size(self):
|
|
return (self.file_size_high << 32) + self.file_size_low
|
|
|
|
@property
|
|
def file_index(self):
|
|
return (self.file_index_high << 32) + self.file_index_low
|
|
|
|
|
|
GetFileInformationByHandle = ctypes.windll.kernel32.GetFileInformationByHandle
|
|
GetFileInformationByHandle.restype = ctypes.wintypes.BOOL
|
|
GetFileInformationByHandle.argtypes = (
|
|
ctypes.wintypes.HANDLE,
|
|
ctypes.POINTER(BY_HANDLE_FILE_INFORMATION),
|
|
)
|
|
|
|
|
|
class SHFILEOPSTRUCT(ctypes.Structure):
|
|
_fields_ = [
|
|
('status_dialog', ctypes.wintypes.HWND),
|
|
('operation', ctypes.wintypes.UINT),
|
|
('from_', ctypes.wintypes.LPWSTR),
|
|
('to', ctypes.wintypes.LPWSTR),
|
|
('flags', FILEOP_FLAGS),
|
|
('operations_aborted', ctypes.wintypes.BOOL),
|
|
('name_mapping_handles', ctypes.wintypes.LPVOID),
|
|
('progress_title', ctypes.wintypes.LPWSTR),
|
|
]
|
|
|
|
|
|
_SHFileOperation = ctypes.windll.shell32.SHFileOperationW
|
|
_SHFileOperation.argtypes = [ctypes.POINTER(SHFILEOPSTRUCT)]
|
|
_SHFileOperation.restype = ctypes.c_int
|
|
|
|
FOF_ALLOWUNDO = 64
|
|
FOF_NOCONFIRMATION = 16
|
|
FO_DELETE = 3
|
|
|
|
ReplaceFile = ctypes.windll.kernel32.ReplaceFileW
|
|
ReplaceFile.restype = ctypes.wintypes.BOOL
|
|
ReplaceFile.argtypes = [
|
|
ctypes.wintypes.LPWSTR,
|
|
ctypes.wintypes.LPWSTR,
|
|
ctypes.wintypes.LPWSTR,
|
|
ctypes.wintypes.DWORD,
|
|
ctypes.wintypes.LPVOID,
|
|
ctypes.wintypes.LPVOID,
|
|
]
|
|
|
|
REPLACEFILE_WRITE_THROUGH = 0x1
|
|
REPLACEFILE_IGNORE_MERGE_ERRORS = 0x2
|
|
REPLACEFILE_IGNORE_ACL_ERRORS = 0x4
|
|
|
|
|
|
class STAT_STRUCT(ctypes.Structure):
|
|
_fields_ = [
|
|
('dev', ctypes.c_uint),
|
|
('ino', ctypes.c_ushort),
|
|
('mode', ctypes.c_ushort),
|
|
('nlink', ctypes.c_short),
|
|
('uid', ctypes.c_short),
|
|
('gid', ctypes.c_short),
|
|
('rdev', ctypes.c_uint),
|
|
# the following 4 fields are ctypes.c_uint64 for _stat64
|
|
('size', ctypes.c_uint),
|
|
('atime', ctypes.c_uint),
|
|
('mtime', ctypes.c_uint),
|
|
('ctime', ctypes.c_uint),
|
|
]
|
|
|
|
|
|
_wstat = ctypes.windll.msvcrt._wstat
|
|
_wstat.argtypes = [ctypes.wintypes.LPWSTR, ctypes.POINTER(STAT_STRUCT)]
|
|
_wstat.restype = ctypes.c_int
|
|
|
|
FILE_NOTIFY_CHANGE_LAST_WRITE = 0x10
|
|
|
|
FindFirstChangeNotification = ctypes.windll.kernel32.FindFirstChangeNotificationW
|
|
FindFirstChangeNotification.argtypes = (
|
|
ctypes.wintypes.LPWSTR,
|
|
ctypes.wintypes.BOOL,
|
|
ctypes.wintypes.DWORD,
|
|
)
|
|
FindFirstChangeNotification.restype = ctypes.wintypes.HANDLE
|
|
|
|
FindCloseChangeNotification = ctypes.windll.kernel32.FindCloseChangeNotification
|
|
FindCloseChangeNotification.argtypes = (ctypes.wintypes.HANDLE,)
|
|
FindCloseChangeNotification.restype = ctypes.wintypes.BOOL
|
|
|
|
FindNextChangeNotification = ctypes.windll.kernel32.FindNextChangeNotification
|
|
FindNextChangeNotification.argtypes = (ctypes.wintypes.HANDLE,)
|
|
FindNextChangeNotification.restype = ctypes.wintypes.BOOL
|
|
|
|
FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000
|
|
IO_REPARSE_TAG_SYMLINK = 0xA000000C
|
|
FSCTL_GET_REPARSE_POINT = 0x900A8
|
|
|
|
LPDWORD = ctypes.POINTER(ctypes.wintypes.DWORD)
|
|
LPOVERLAPPED = ctypes.wintypes.LPVOID
|
|
|
|
DeviceIoControl = ctypes.windll.kernel32.DeviceIoControl
|
|
DeviceIoControl.argtypes = [
|
|
ctypes.wintypes.HANDLE,
|
|
ctypes.wintypes.DWORD,
|
|
ctypes.wintypes.LPVOID,
|
|
ctypes.wintypes.DWORD,
|
|
ctypes.wintypes.LPVOID,
|
|
ctypes.wintypes.DWORD,
|
|
LPDWORD,
|
|
LPOVERLAPPED,
|
|
]
|
|
DeviceIoControl.restype = ctypes.wintypes.BOOL
|
|
|
|
|
|
class REPARSE_DATA_BUFFER(ctypes.Structure):
|
|
_fields_ = [
|
|
('tag', ctypes.c_ulong),
|
|
('data_length', ctypes.c_ushort),
|
|
('reserved', ctypes.c_ushort),
|
|
('substitute_name_offset', ctypes.c_ushort),
|
|
('substitute_name_length', ctypes.c_ushort),
|
|
('print_name_offset', ctypes.c_ushort),
|
|
('print_name_length', ctypes.c_ushort),
|
|
('flags', ctypes.c_ulong),
|
|
('path_buffer', ctypes.c_byte * 1),
|
|
]
|
|
|
|
def get_print_name(self):
|
|
wchar_size = ctypes.sizeof(ctypes.wintypes.WCHAR)
|
|
arr_typ = ctypes.wintypes.WCHAR * (self.print_name_length // wchar_size)
|
|
data = ctypes.byref(self.path_buffer, self.print_name_offset)
|
|
return ctypes.cast(data, ctypes.POINTER(arr_typ)).contents.value
|
|
|
|
def get_substitute_name(self):
|
|
wchar_size = ctypes.sizeof(ctypes.wintypes.WCHAR)
|
|
arr_typ = ctypes.wintypes.WCHAR * (self.substitute_name_length // wchar_size)
|
|
data = ctypes.byref(self.path_buffer, self.substitute_name_offset)
|
|
return ctypes.cast(data, ctypes.POINTER(arr_typ)).contents.value
|