mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Wrap the basic win32 file apis
Want to eliminate use of pywin32 gradually
This commit is contained in:
parent
003a22b47c
commit
0341bf40db
@ -180,6 +180,39 @@ class BuildTest(unittest.TestCase):
|
|||||||
if isinstance(fmt, bytes):
|
if isinstance(fmt, bytes):
|
||||||
fmt = fmt.decode('ascii')
|
fmt = fmt.decode('ascii')
|
||||||
self.assertEqual(unicode_type(time.strftime(fmt.replace('%e', '%#d'), t)), x)
|
self.assertEqual(unicode_type(time.strftime(fmt.replace('%e', '%#d'), t)), x)
|
||||||
|
tdir = winutil.temp_path()
|
||||||
|
path = os.path.join(tdir, 'test-create-file.txt')
|
||||||
|
h = winutil.create_file(
|
||||||
|
path, winutil.GENERIC_READ | winutil.GENERIC_WRITE, 0, winutil.OPEN_ALWAYS, winutil.FILE_ATTRIBUTE_NORMAL)
|
||||||
|
winutil.close_handle(h)
|
||||||
|
self.assertRaises(OSError, winutil.close_handle, h)
|
||||||
|
winutil.delete_file(path)
|
||||||
|
self.assertRaises(OSError, winutil.delete_file, path)
|
||||||
|
self.assertRaises(OSError, winutil.create_file,
|
||||||
|
os.path.join(path, 'cannot'), winutil.GENERIC_READ, 0, winutil.OPEN_ALWAYS, winutil.FILE_ATTRIBUTE_NORMAL)
|
||||||
|
sz = 23
|
||||||
|
data = os.urandom(sz)
|
||||||
|
open(path, 'wb').write(data)
|
||||||
|
h = winutil.create_file(
|
||||||
|
path, winutil.GENERIC_READ | winutil.GENERIC_WRITE, 0, winutil.OPEN_ALWAYS, winutil.FILE_ATTRIBUTE_NORMAL)
|
||||||
|
self.assertEqual(winutil.get_file_size(h), sz)
|
||||||
|
self.assertRaises(OSError, winutil.set_file_pointer, h, 23, 23)
|
||||||
|
self.assertEqual(winutil.read_file(h), data)
|
||||||
|
self.assertEqual(winutil.read_file(h), b'')
|
||||||
|
winutil.set_file_pointer(h, 3)
|
||||||
|
self.assertEqual(winutil.read_file(h), data[3:])
|
||||||
|
winutil.close_handle(h)
|
||||||
|
self.assertEqual(winutil.nlinks(path), 1)
|
||||||
|
npath = path + '.2'
|
||||||
|
winutil.create_hard_link(npath, path)
|
||||||
|
self.assertEqual(open(npath, 'rb').read(), data)
|
||||||
|
self.assertEqual(winutil.nlinks(path), 2)
|
||||||
|
winutil.delete_file(path)
|
||||||
|
self.assertEqual(winutil.nlinks(npath), 1)
|
||||||
|
winutil.set_file_attributes(npath, winutil.FILE_ATTRIBUTE_READONLY)
|
||||||
|
self.assertRaises(OSError, winutil.delete_file, npath)
|
||||||
|
winutil.set_file_attributes(npath, winutil.FILE_ATTRIBUTE_NORMAL)
|
||||||
|
winutil.delete_file(npath)
|
||||||
|
|
||||||
def test_sqlite(self):
|
def test_sqlite(self):
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
@ -219,34 +219,10 @@ def case_preserving_open_file(path, mode='wb', mkdir_mode=0o777):
|
|||||||
return ans, fpath
|
return ans, fpath
|
||||||
|
|
||||||
|
|
||||||
def old_windows_get_fileid(path):
|
|
||||||
# we dont use this anymore as the win32 implementation reads the windows
|
|
||||||
# registry to convert file times which is slow and breaks on systems with
|
|
||||||
# registry issues.
|
|
||||||
import win32file
|
|
||||||
from pywintypes import error
|
|
||||||
if isbytestring(path):
|
|
||||||
path = path.decode(filesystem_encoding)
|
|
||||||
try:
|
|
||||||
h = win32file.CreateFileW(path, 0, 0, None, win32file.OPEN_EXISTING,
|
|
||||||
win32file.FILE_FLAG_BACKUP_SEMANTICS, 0)
|
|
||||||
try:
|
|
||||||
data = win32file.GetFileInformationByHandle(h)
|
|
||||||
finally:
|
|
||||||
win32file.CloseHandle(h)
|
|
||||||
except (error, EnvironmentError):
|
|
||||||
return None
|
|
||||||
return data[4], data[8], data[9]
|
|
||||||
|
|
||||||
|
|
||||||
def windows_get_fileid(path):
|
def windows_get_fileid(path):
|
||||||
''' The fileid uniquely identifies actual file contents (it is the same for
|
''' The fileid uniquely identifies actual file contents (it is the same for
|
||||||
all hardlinks to a file). Similar to inode number on linux. '''
|
all hardlinks to a file). Similar to inode number on linux. '''
|
||||||
try:
|
get_file_id = plugins['winutil'][0].get_file_id
|
||||||
get_file_id = plugins['winutil'][0].get_file_id
|
|
||||||
except AttributeError:
|
|
||||||
# running from source without updating binary
|
|
||||||
return old_windows_get_fileid(path)
|
|
||||||
if isbytestring(path):
|
if isbytestring(path):
|
||||||
path = path.decode(filesystem_encoding)
|
path = path.decode(filesystem_encoding)
|
||||||
with suppress(OSError):
|
with suppress(OSError):
|
||||||
|
@ -369,7 +369,14 @@ winutil_strftime(PyObject *self, PyObject *args)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char winutil_doc[] = "Defines utility methods to interface with windows.";
|
static PyObject*
|
||||||
|
winutil_close_handle(PyObject *self, PyObject *pyhandle) {
|
||||||
|
if (!PyLong_Check(pyhandle)) { PyErr_SetString(PyExc_TypeError, "handle must be an int"); return NULL; }
|
||||||
|
if (!CloseHandle(PyLong_AsVoidPtr(pyhandle))) return PyErr_SetFromWindowsErr(0);
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char winutil_doc[] = "Defines utility methods to interface with windows.";
|
||||||
extern PyObject *winutil_add_to_recent_docs(PyObject *self, PyObject *args);
|
extern PyObject *winutil_add_to_recent_docs(PyObject *self, PyObject *args);
|
||||||
extern PyObject *winutil_file_association(PyObject *self, PyObject *args);
|
extern PyObject *winutil_file_association(PyObject *self, PyObject *args);
|
||||||
extern PyObject *winutil_friendly_name(PyObject *self, PyObject *args);
|
extern PyObject *winutil_friendly_name(PyObject *self, PyObject *args);
|
||||||
@ -377,6 +384,14 @@ extern PyObject *winutil_notify_associations_changed(PyObject *self, PyObject *a
|
|||||||
extern PyObject *winutil_move_to_trash(PyObject *self, PyObject *args);
|
extern PyObject *winutil_move_to_trash(PyObject *self, PyObject *args);
|
||||||
extern PyObject *winutil_manage_shortcut(PyObject *self, PyObject *args);
|
extern PyObject *winutil_manage_shortcut(PyObject *self, PyObject *args);
|
||||||
extern PyObject *winutil_get_file_id(PyObject *self, PyObject *args);
|
extern PyObject *winutil_get_file_id(PyObject *self, PyObject *args);
|
||||||
|
extern PyObject *winutil_create_file(PyObject *self, PyObject *args);
|
||||||
|
extern PyObject *winutil_delete_file(PyObject *self, PyObject *args);
|
||||||
|
extern PyObject *winutil_create_hard_link(PyObject *self, PyObject *args);
|
||||||
|
extern PyObject *winutil_nlinks(PyObject *self, PyObject *args);
|
||||||
|
extern PyObject *winutil_set_file_attributes(PyObject *self, PyObject *args);
|
||||||
|
extern PyObject *winutil_get_file_size(PyObject *self, PyObject *args);
|
||||||
|
extern PyObject *winutil_set_file_pointer(PyObject *self, PyObject *args);
|
||||||
|
extern PyObject *winutil_read_file(PyObject *self, PyObject *args);
|
||||||
|
|
||||||
static PyMethodDef winutil_methods[] = {
|
static PyMethodDef winutil_methods[] = {
|
||||||
{"special_folder_path", winutil_folder_path, METH_VARARGS,
|
{"special_folder_path", winutil_folder_path, METH_VARARGS,
|
||||||
@ -472,6 +487,42 @@ be a unicode string. Returns unicode strings."
|
|||||||
"get_file_id(path)\n\nGet the windows file id (volume_num, file_index_high, file_index_low)"
|
"get_file_id(path)\n\nGet the windows file id (volume_num, file_index_high, file_index_low)"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{"create_file", (PyCFunction)winutil_create_file, METH_VARARGS,
|
||||||
|
"create_file(path, desired_access, share_mode, creation_disposition, flags_and_attributes)\n\nWrapper for CreateFile"
|
||||||
|
},
|
||||||
|
|
||||||
|
{"get_file_size", (PyCFunction)winutil_get_file_size, METH_O,
|
||||||
|
"get_file_size(handle)\n\nWrapper for GetFileSizeEx"
|
||||||
|
},
|
||||||
|
|
||||||
|
{"set_file_pointer", (PyCFunction)winutil_set_file_pointer, METH_VARARGS,
|
||||||
|
"set_file_pointer(handle, pos, method=FILE_BEGIN)\n\nWrapper for SetFilePointer"
|
||||||
|
},
|
||||||
|
|
||||||
|
{"read_file", (PyCFunction)winutil_read_file, METH_VARARGS,
|
||||||
|
"set_file_pointer(handle, chunk_size=16KB)\n\nWrapper for ReadFile"
|
||||||
|
},
|
||||||
|
|
||||||
|
{"close_handle", (PyCFunction)winutil_close_handle, METH_O,
|
||||||
|
"close_handle(handle)\n\nWrapper for CloseHandle"
|
||||||
|
},
|
||||||
|
|
||||||
|
{"delete_file", (PyCFunction)winutil_delete_file, METH_VARARGS,
|
||||||
|
"delete_file(path)\n\nWrapper for DeleteFile"
|
||||||
|
},
|
||||||
|
|
||||||
|
{"create_hard_link", (PyCFunction)winutil_create_hard_link, METH_VARARGS,
|
||||||
|
"create_hard_link(path, existing_path)\n\nWrapper for CreateHardLink"
|
||||||
|
},
|
||||||
|
|
||||||
|
{"nlinks", (PyCFunction)winutil_nlinks, METH_VARARGS,
|
||||||
|
"nlinks(path)\n\nReturn the number of hardlinks"
|
||||||
|
},
|
||||||
|
|
||||||
|
{"set_file_attributes", (PyCFunction)winutil_set_file_attributes, METH_VARARGS,
|
||||||
|
"set_file_attributes(path, attrs)\n\nWrapper for SetFileAttributes"
|
||||||
|
},
|
||||||
|
|
||||||
{NULL, NULL, 0, NULL}
|
{NULL, NULL, 0, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -514,6 +565,27 @@ CALIBRE_MODINIT_FUNC PyInit_winutil(void) {
|
|||||||
PyModule_AddIntConstant(m, "CSIDL_PROFILE", CSIDL_PROFILE);
|
PyModule_AddIntConstant(m, "CSIDL_PROFILE", CSIDL_PROFILE);
|
||||||
PyModule_AddIntConstant(m, "CSIDL_STARTUP", CSIDL_STARTUP);
|
PyModule_AddIntConstant(m, "CSIDL_STARTUP", CSIDL_STARTUP);
|
||||||
PyModule_AddIntConstant(m, "CSIDL_COMMON_STARTUP", CSIDL_COMMON_STARTUP);
|
PyModule_AddIntConstant(m, "CSIDL_COMMON_STARTUP", CSIDL_COMMON_STARTUP);
|
||||||
|
PyModule_AddIntConstant(m, "CREATE_NEW", CREATE_NEW);
|
||||||
|
PyModule_AddIntConstant(m, "CREATE_ALWAYS", CREATE_ALWAYS);
|
||||||
|
PyModule_AddIntConstant(m, "OPEN_EXISTING", OPEN_EXISTING);
|
||||||
|
PyModule_AddIntConstant(m, "OPEN_ALWAYS", OPEN_ALWAYS);
|
||||||
|
PyModule_AddIntConstant(m, "TRUNCATE_EXISTING", TRUNCATE_EXISTING);
|
||||||
|
PyModule_AddIntConstant(m, "FILE_SHARE_READ", FILE_SHARE_READ);
|
||||||
|
PyModule_AddIntConstant(m, "FILE_SHARE_WRITE", FILE_SHARE_WRITE);
|
||||||
|
PyModule_AddIntConstant(m, "FILE_SHARE_DELETE", FILE_SHARE_DELETE);
|
||||||
|
PyModule_AddIntConstant(m, "FILE_SHARE_VALID_FLAGS", FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE);
|
||||||
|
PyModule_AddIntConstant(m, "FILE_ATTRIBUTE_READONLY", FILE_ATTRIBUTE_READONLY);
|
||||||
|
PyModule_AddIntConstant(m, "FILE_ATTRIBUTE_NORMAL", FILE_ATTRIBUTE_NORMAL);
|
||||||
|
PyModule_AddIntConstant(m, "FILE_ATTRIBUTE_TEMPORARY", FILE_ATTRIBUTE_TEMPORARY);
|
||||||
|
PyModule_AddIntConstant(m, "FILE_FLAG_DELETE_ON_CLOSE", FILE_FLAG_DELETE_ON_CLOSE);
|
||||||
|
PyModule_AddIntConstant(m, "FILE_FLAG_SEQUENTIAL_SCAN", FILE_FLAG_SEQUENTIAL_SCAN);
|
||||||
|
PyModule_AddIntConstant(m, "FILE_FLAG_RANDOM_ACCESS", FILE_FLAG_RANDOM_ACCESS);
|
||||||
|
PyModule_AddIntConstant(m, "GENERIC_READ", GENERIC_READ);
|
||||||
|
PyModule_AddIntConstant(m, "GENERIC_WRITE", GENERIC_WRITE);
|
||||||
|
PyModule_AddIntConstant(m, "DELETE", DELETE);
|
||||||
|
PyModule_AddIntConstant(m, "FILE_BEGIN", FILE_BEGIN);
|
||||||
|
PyModule_AddIntConstant(m, "FILE_CURRENT", FILE_CURRENT);
|
||||||
|
PyModule_AddIntConstant(m, "FILE_END", FILE_END);
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
@ -131,16 +131,108 @@ py_to_wchar(PyObject *obj, wchar_raii *output) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
wchar_t *buf = PyUnicode_AsWideCharString(obj, NULL);
|
wchar_t *buf = PyUnicode_AsWideCharString(obj, NULL);
|
||||||
|
if (!buf) { PyErr_NoMemory(); return 0; }
|
||||||
output->set_ptr(buf);
|
output->set_ptr(buf);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
py_to_wchar_no_none(PyObject *obj, wchar_raii *output) {
|
||||||
|
if (!PyUnicode_Check(obj)) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "unicode object expected");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
wchar_t *buf = PyUnicode_AsWideCharString(obj, NULL);
|
||||||
|
if (!buf) { PyErr_NoMemory(); return 0; }
|
||||||
|
output->set_ptr(buf);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
set_error_from_file_handle(HANDLE h) {
|
||||||
|
int error_code = GetLastError();
|
||||||
|
wchar_t buf[4096] = {0};
|
||||||
|
if (GetFinalPathNameByHandleW(h, buf, 4095, FILE_NAME_OPENED)) {
|
||||||
|
PyObject *fname = PyUnicode_FromWideChar(buf, -1);
|
||||||
|
if (fname) {
|
||||||
|
PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, error_code, fname);
|
||||||
|
Py_DECREF(fname);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return PyErr_SetFromWindowsErr(error_code);
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
|
PyObject*
|
||||||
|
winutil_read_file(PyObject *self, PyObject *args) {
|
||||||
|
unsigned long chunk_size = 16 * 1024;
|
||||||
|
PyObject *handle;
|
||||||
|
if (!PyArg_ParseTuple(args, "O!|k", &PyLong_Type, &handle, &chunk_size)) return NULL;
|
||||||
|
PyObject *ans = PyBytes_FromStringAndSize(NULL, chunk_size);
|
||||||
|
if (!ans) return PyErr_NoMemory();
|
||||||
|
DWORD bytes_read;
|
||||||
|
if (!ReadFile(PyLong_AsVoidPtr(handle), PyBytes_AS_STRING(ans), chunk_size, &bytes_read, NULL)) {
|
||||||
|
Py_DECREF(ans);
|
||||||
|
return set_error_from_file_handle(PyLong_AsVoidPtr(handle));
|
||||||
|
}
|
||||||
|
if (bytes_read < chunk_size) _PyBytes_Resize(&ans, bytes_read);
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PyObject*
|
||||||
|
winutil_get_file_size(PyObject *self, PyObject *pyhandle) {
|
||||||
|
if (!PyLong_Check(pyhandle)) { PyErr_SetString(PyExc_TypeError, "handle must be an int"); return NULL; }
|
||||||
|
LARGE_INTEGER ans = {0};
|
||||||
|
if (!GetFileSizeEx(PyLong_AsVoidPtr(pyhandle), &ans)) return set_error_from_file_handle(PyLong_AsVoidPtr(pyhandle));
|
||||||
|
return PyLong_FromLongLong(ans.QuadPart);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject*
|
||||||
|
winutil_set_file_pointer(PyObject *self, PyObject *args) {
|
||||||
|
PyObject *handle; unsigned long move_method = FILE_BEGIN;
|
||||||
|
LARGE_INTEGER pos = {0};
|
||||||
|
if (!PyArg_ParseTuple(args, "O!L|k", &PyLong_Type, &handle, &pos.QuadPart, &move_method)) return NULL;
|
||||||
|
LARGE_INTEGER ans = {0};
|
||||||
|
if (!SetFilePointerEx(PyLong_AsVoidPtr(handle), pos, &ans, move_method)) return set_error_from_file_handle(PyLong_AsVoidPtr(handle));
|
||||||
|
return PyLong_FromLongLong(ans.QuadPart);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject*
|
||||||
|
winutil_create_file(PyObject *self, PyObject *args) {
|
||||||
|
wchar_raii path;
|
||||||
|
unsigned long desired_access, share_mode, creation_disposition, flags_and_attributes;
|
||||||
|
if (!PyArg_ParseTuple(args, "O&kkkk", py_to_wchar_no_none, &path, &desired_access, &share_mode, &creation_disposition, &flags_and_attributes)) return NULL;
|
||||||
|
HANDLE h = CreateFileW(
|
||||||
|
path.ptr(), desired_access, share_mode, NULL, creation_disposition, flags_and_attributes, NULL
|
||||||
|
);
|
||||||
|
if (h == INVALID_HANDLE_VALUE) return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, 0, PyTuple_GET_ITEM(args, 0));
|
||||||
|
return PyLong_FromVoidPtr(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject*
|
||||||
|
winutil_delete_file(PyObject *self, PyObject *args) {
|
||||||
|
wchar_raii path;
|
||||||
|
if (!PyArg_ParseTuple(args, "O&", py_to_wchar_no_none, &path)) return NULL;
|
||||||
|
if (!DeleteFileW(path.ptr())) return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, 0, PyTuple_GET_ITEM(args, 0));
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject*
|
||||||
|
winutil_create_hard_link(PyObject *self, PyObject *args) {
|
||||||
|
wchar_raii path, existing_path;
|
||||||
|
if (!PyArg_ParseTuple(args, "O&O&", py_to_wchar_no_none, &path, py_to_wchar_no_none, &existing_path)) return NULL;
|
||||||
|
if (!CreateHardLinkW(path.ptr(), existing_path.ptr(), NULL)) return PyErr_SetExcFromWindowsErrWithFilenameObjects(PyExc_OSError, 0, PyTuple_GET_ITEM(args, 0), PyTuple_GET_ITEM(args, 1));
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PyObject*
|
PyObject*
|
||||||
winutil_get_file_id(PyObject *self, PyObject *args) {
|
winutil_get_file_id(PyObject *self, PyObject *args) {
|
||||||
wchar_raii path;
|
wchar_raii path;
|
||||||
if (!PyArg_ParseTuple(args, "O&", py_to_wchar, &path)) return NULL;
|
if (!PyArg_ParseTuple(args, "O&", py_to_wchar_no_none, &path)) return NULL;
|
||||||
if (path.ptr()) {
|
if (path.ptr()) {
|
||||||
handle_raii file_handle(CreateFileW(path.ptr(), 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL));
|
handle_raii file_handle(CreateFileW(path.ptr(), 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL));
|
||||||
if (!file_handle) return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, 0, PyTuple_GET_ITEM(args, 0));
|
if (!file_handle) return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, 0, PyTuple_GET_ITEM(args, 0));
|
||||||
@ -153,6 +245,28 @@ winutil_get_file_id(PyObject *self, PyObject *args) {
|
|||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyObject*
|
||||||
|
winutil_nlinks(PyObject *self, PyObject *args) {
|
||||||
|
wchar_raii path;
|
||||||
|
if (!PyArg_ParseTuple(args, "O&", py_to_wchar_no_none, &path)) return NULL;
|
||||||
|
handle_raii file_handle(CreateFileW(path.ptr(), 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL));
|
||||||
|
if (!file_handle) return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, 0, PyTuple_GET_ITEM(args, 0));
|
||||||
|
BY_HANDLE_FILE_INFORMATION info = {0};
|
||||||
|
BOOL ok = GetFileInformationByHandle(file_handle.ptr(), &info);
|
||||||
|
if (!ok) return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, 0, PyTuple_GET_ITEM(args, 0));
|
||||||
|
unsigned long ans = info.nNumberOfLinks;
|
||||||
|
return PyLong_FromUnsignedLong(ans);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject*
|
||||||
|
winutil_set_file_attributes(PyObject *self, PyObject *args) {
|
||||||
|
wchar_raii path; unsigned long attrs;
|
||||||
|
if (!PyArg_ParseTuple(args, "O&k", py_to_wchar_no_none, &path, &attrs)) return NULL;
|
||||||
|
if (!SetFileAttributes(path.ptr(), attrs)) return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, 0, PyTuple_GET_ITEM(args, 0));
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
winutil_add_to_recent_docs(PyObject *self, PyObject *args) {
|
winutil_add_to_recent_docs(PyObject *self, PyObject *args) {
|
||||||
wchar_raii path, app_id;
|
wchar_raii path, app_id;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user