1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586 |
- # Copyright 2017 Virgil Dupras
- # This software is licensed under the "BSD" License as described in the "LICENSE" file,
- # which should be included with this package. The terms are also available at
- # http://www.hardcoded.net/licenses/bsd_license
- from __future__ import unicode_literals
- from ctypes import (windll, Structure, byref, c_uint,
- create_unicode_buffer, addressof)
- from ctypes.wintypes import HWND, UINT, LPCWSTR, BOOL
- import os.path as op
- from .compat import text_type
- kernel32 = windll.kernel32
- GetShortPathNameW = kernel32.GetShortPathNameW
- shell32 = windll.shell32
- SHFileOperationW = shell32.SHFileOperationW
- class SHFILEOPSTRUCTW(Structure):
- _fields_ = [
- ("hwnd", HWND),
- ("wFunc", UINT),
- ("pFrom", LPCWSTR),
- ("pTo", LPCWSTR),
- ("fFlags", c_uint),
- ("fAnyOperationsAborted", BOOL),
- ("hNameMappings", c_uint),
- ("lpszProgressTitle", LPCWSTR),
- ]
- FO_MOVE = 1
- FO_COPY = 2
- FO_DELETE = 3
- FO_RENAME = 4
- FOF_MULTIDESTFILES = 1
- FOF_SILENT = 4
- FOF_NOCONFIRMATION = 16
- FOF_ALLOWUNDO = 64
- FOF_NOERRORUI = 1024
- def get_short_path_name(long_name):
- if not long_name.startswith('\\\\?\\'):
- long_name = '\\\\?\\' + long_name
- buf_size = GetShortPathNameW(long_name, None, 0)
- output = create_unicode_buffer(buf_size)
- GetShortPathNameW(long_name, output, buf_size)
- return output.value[4:] # Remove '\\?\' for SHFileOperationW
- def send2trash(path):
- if not isinstance(path, text_type):
- path = text_type(path, 'mbcs')
- if not op.isabs(path):
- path = op.abspath(path)
- path = get_short_path_name(path)
- fileop = SHFILEOPSTRUCTW()
- fileop.hwnd = 0
- fileop.wFunc = FO_DELETE
- # FIX: https://github.com/hsoft/send2trash/issues/17
- # Starting in python 3.6.3 it is no longer possible to use:
- # LPCWSTR(path + '\0') directly as embedded null characters are no longer
- # allowed in strings
- # Workaround
- # - create buffer of c_wchar[] (LPCWSTR is based on this type)
- # - buffer is two c_wchar characters longer (double null terminator)
- # - cast the address of the buffer to a LPCWSTR
- # NOTE: based on how python allocates memory for these types they should
- # always be zero, if this is ever not true we can go back to explicitly
- # setting the last two characters to null using buffer[index] = '\0'.
- buffer = create_unicode_buffer(path, len(path)+2)
- fileop.pFrom = LPCWSTR(addressof(buffer))
- fileop.pTo = None
- fileop.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT
- fileop.fAnyOperationsAborted = 0
- fileop.hNameMappings = 0
- fileop.lpszProgressTitle = None
- result = SHFileOperationW(byref(fileop))
- if result:
- raise WindowsError(None, None, path, result)
|