ERROR_MOD_NOT_FOUND(126)可能是由于
windll.CloseHandle(hfile),它尝试加载“
closehandle.dll”。它不见了
kernel32。
这是处理结点和符号链接的替代实现。
ctypes定义
import ctypesfrom ctypes import wintypeskernel32 = ctypes.WinDLL('kernel32', use_last_error=True)FILE_READ_ATTRIBUTES = 0x0080OPEN_EXISTING = 3FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000FILE_FLAG_BACKUP_SEMANTICS = 0x02000000FILE_ATTRIBUTE_REPARSE_POINT = 0x0400IO_REPARSE_TAG_MOUNT_POINT = 0xA0000003IO_REPARSE_TAG_SYMlink = 0xA000000CFSCTL_GET_REPARSE_POINT = 0x000900A8MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 0x4000LPDWORD = ctypes.POINTER(wintypes.DWORD)LPWIN32_FIND_DATA = ctypes.POINTER(wintypes.WIN32_FIND_DATAW)INVALID_HANDLE_VALUE = wintypes.HANDLE(-1).valuedef IsReparseTagNameSurrogate(tag): return bool(tag & 0x20000000)def _check_invalid_handle(result, func, args): if result == INVALID_HANDLE_VALUE: raise ctypes.WinError(ctypes.get_last_error()) return argsdef _check_bool(result, func, args): if not result: raise ctypes.WinError(ctypes.get_last_error()) return argskernel32.FindFirstFileW.errcheck = _check_invalid_handlekernel32.FindFirstFileW.restype = wintypes.HANDLEkernel32.FindFirstFileW.argtypes = ( wintypes.LPCWSTR, # _In_ lpFileName LPWIN32_FIND_DATA) # _Out_ lpFindFileDatakernel32.FindClose.argtypes = ( wintypes.HANDLE,) # _Inout_ hFindFilekernel32.CreateFileW.errcheck = _check_invalid_handlekernel32.CreateFileW.restype = wintypes.HANDLEkernel32.CreateFileW.argtypes = ( wintypes.LPCWSTR, # _In_ lpFileName wintypes.DWORD, # _In_ dwDesiredAccess wintypes.DWORD, # _In_ dwShareMode wintypes.LPVOID, # _In_opt_ lpSecurityAttributes wintypes.DWORD, # _In_ dwCreationDisposition wintypes.DWORD, # _In_ dwFlagsAndAttributes wintypes.HANDLE) # _In_opt_ hTemplateFilekernel32.CloseHandle.argtypes = ( wintypes.HANDLE,) # _In_ hObjectkernel32.DeviceIoControl.errcheck = _check_boolkernel32.DeviceIoControl.argtypes = ( wintypes.HANDLE, # _In_ hDevice wintypes.DWORD, # _In_ dwIoControlCode wintypes.LPVOID, # _In_opt_ lpInBuffer wintypes.DWORD, # _In_ nInBufferSize wintypes.LPVOID, # _Out_opt_ lpOutBuffer wintypes.DWORD, # _In_ nOutBufferSize LPDWORD, # _Out_opt_ lpBytesReturned wintypes.LPVOID) # _Inout_opt_ lpOverlappedclass REPARSE_DATA_BUFFER(ctypes.Structure): class ReparseData(ctypes.Union): class linkData(ctypes.Structure): _fields_ = (('SubstituteNameOffset', wintypes.USHORT), ('SubstituteNameLength', wintypes.USHORT), ('PrintNameOffset', wintypes.USHORT), ('PrintNameLength', wintypes.USHORT)) @property def PrintName(self): dt = wintypes.WCHAR * (self.PrintNameLength // ctypes.sizeof(wintypes.WCHAR)) name = dt.from_address(ctypes.addressof(self.PathBuffer) + self.PrintNameOffset).value if name.startswith(r'??'): name = r'\?' + name[3:] # NT => Windows return name class SymboliclinkData(linkData): _fields_ = (('Flags', wintypes.ULONG), ('PathBuffer', wintypes.BYTE * 0)) class MountPointData(linkData): _fields_ = (('PathBuffer', wintypes.BYTE * 0),) class GenericData(ctypes.Structure): _fields_ = (('DataBuffer', wintypes.BYTE * 0),) _fields_ = (('SymboliclinkReparseBuffer', SymboliclinkData), ('MountPointReparseBuffer', MountPointData), ('GenericReparseBuffer', GenericData)) _fields_ = (('ReparseTag', wintypes.ULONG), ('ReparseDataLength', wintypes.USHORT), ('Reserved', wintypes.USHORT), ('ReparseData', ReparseData)) _anonymous_ = ('ReparseData',)
职能
def islink(path): data = wintypes.WIN32_FIND_DATAW() kernel32.FindClose(kernel32.FindFirstFileW(path, ctypes.byref(data))) if not data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT: return False return IsReparseTagNameSurrogate(data.dwReserved0)def readlink(path): n = wintypes.DWORd() buf = (wintypes.BYTE * MAXIMUM_REPARSE_DATA_BUFFER_SIZE)() flags = FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS handle = kernel32.CreateFileW(path, FILE_READ_ATTRIBUTES, 0, None, OPEN_EXISTING, flags, None) try: kernel32.DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, None, 0, buf, ctypes.sizeof(buf), ctypes.byref(n), None) finally: kernel32.CloseHandle(handle) rb = REPARSE_DATA_BUFFER.from_buffer(buf) tag = rb.ReparseTag if tag == IO_REPARSE_TAG_SYMlink: return rb.SymboliclinkReparseBuffer.PrintName if tag == IO_REPARSE_TAG_MOUNT_POINT: return rb.MountPointReparseBuffer.PrintName if not IsReparseTagNameSurrogate(tag): raise ValueError("not a link") raise ValueError("unsupported reparse tag: %d" % tag)
例
>>> sys.version'2.7.13 (v2.7.13:a06454b1afa1, Dec 17 2016, 20:53:40) [MSC v.1500 64 bit (AMD64)]'>>> os.system(r'mklink /d spam C:Windows')symbolic link created for spam <<===>> C:Windows0>>> islink('spam')True>>> readlink('spam')u'C:\Windows'>>> islink('C:/documents and Settings') # junctionTrue>>> readlink('C:/documents and Settings')u'C:\Users'>>> islink('C:/Users/All Users') # symlinkdTrue>>> readlink('C:/Users/All Users')u'C:\ProgramData'
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)