gpodder/src/gpodder/utilwin32ctypes.py

159 lines
5.0 KiB
Python

# -*- coding: utf-8 -*-
#
# gPodder - A media aggregator and podcast client
# Copyright (c) 2005-2018 The gPodder Team
# Copyright (c) 2018 Eric Le Lay
#
# gPodder is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# gPodder is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import ctypes
from ctypes import HRESULT, Structure, byref, c_ulonglong
from ctypes.wintypes import (BOOL, BYTE, DWORD, HANDLE, LPCWSTR,
PULARGE_INTEGER, WORD)
from uuid import UUID
from win32ctypes.core.ctypes._util import check_zero, function_factory
# Use a local copy of dlls.
kernel32 = ctypes.WinDLL('kernel32')
shell32 = ctypes.WinDLL('shell32')
ole32 = ctypes.WinDLL('ole32')
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa373931%28v=vs.85%29.aspx
class GUID(ctypes.Structure):
_fields_ = [
("Data1", DWORD),
("Data2", WORD),
("Data3", WORD),
("Data4", BYTE * 8),
]
def __init__(self, uuidstr=None):
uuid = UUID(uuidstr)
Structure.__init__(self)
self.Data1, self.Data2, self.Data3, self.Data4[0], self.Data4[1], rest = uuid.fields
for i in range(2, 8):
self.Data4[i] = rest >> (8 - i - 1) * 8 & 0xff
REFKNOWNFOLDERID = ctypes.POINTER(GUID)
S_OK = HRESULT(0).value
CoTaskMemFree = function_factory(
ole32.CoTaskMemFree,
[ctypes.c_void_p],
None)
_BaseGetDiskFreeSpaceEx = function_factory(
kernel32.GetDiskFreeSpaceExW,
[LPCWSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER],
BOOL, check_zero)
_BaseGetFileAttributes = function_factory(
kernel32.GetFileAttributesW,
[LPCWSTR],
DWORD)
_BaseSHGetKnownFolderPath = function_factory(
shell32.SHGetKnownFolderPath,
[REFKNOWNFOLDERID, DWORD, HANDLE, ctypes.POINTER(ctypes.c_wchar_p)],
HRESULT)
def GetDiskFreeSpaceEx(lpDirectoryName):
lp_dirname = LPCWSTR(lpDirectoryName)
lpFreeBytesAvailable = c_ulonglong(0)
lpTotalNumberOfBytes = c_ulonglong(0)
lpTotalNumberOfFreeBytes = c_ulonglong(0)
_BaseGetDiskFreeSpaceEx(lp_dirname, byref(lpFreeBytesAvailable), byref(lpTotalNumberOfBytes), byref(lpTotalNumberOfFreeBytes))
freeBytesAvailable = lpFreeBytesAvailable.value
totalNumberOfBytes = lpTotalNumberOfBytes.value
totalNumberOfFreeBytes = lpTotalNumberOfFreeBytes.value
return (freeBytesAvailable, totalNumberOfBytes, totalNumberOfFreeBytes)
def GetFileAttributes(lpFileName):
lp_filename = LPCWSTR(lpFileName)
return _BaseGetFileAttributes(lp_filename)
def SHGetKnownFolderPath(rfid, dwFlags):
out_buf = ctypes.c_wchar_p()
try:
ret = _BaseSHGetKnownFolderPath(byref(rfid), dwFlags, None, byref(out_buf))
except WindowsError:
return None
if ret != S_OK:
return None
res = out_buf.value
CoTaskMemFree(out_buf)
return res
# https://msdn.microsoft.com/en-us/library/dd378447(v=vs.85).aspx
class KNOWN_FOLDER_FLAG:
KF_FLAG_DEFAULT = 0x00000000
KF_FLAG_SIMPLE_IDLIST = 0x00000100
KF_FLAG_NOT_PARENT_RELATIVE = 0x00000200
KF_FLAG_DEFAULT_PATH = 0x00000400
KF_FLAG_INIT = 0x00000800
KF_FLAG_NO_ALIAS = 0x00001000
KF_FLAG_DONT_UNEXPAND = 0x00002000
KF_FLAG_DONT_VERIFY = 0x00004000
KF_FLAG_CREATE = 0x00008000
KF_FLAG_NO_PACKAGE_REDIRECTION = 0x00010000
KF_FLAG_NO_APPCONTAINER_REDIRECTION = 0x00010000
KF_FLAG_FORCE_PACKAGE_REDIRECTION = 0x00020000
KF_FLAG_FORCE_APPCONTAINER_REDIRECTION = 0x00020000
KF_FLAG_RETURN_FILTER_REDIRECTION_TARGET = 0x00040000
KF_FLAG_FORCE_APP_DATA_REDIRECTION = 0x00080000
KF_FLAG_ALIAS_ONLY = 0x80000000
# https://msdn.microsoft.com/en-us/library/dd378457(v=vs.85).aspx
class KNOWNFOLDERID:
FOLDERID_Documents = GUID("{FDD39AD0-238F-46AF-ADB4-6C85480369C7}")
def get_documents_folder():
flags = KNOWN_FOLDER_FLAG.KF_FLAG_DEFAULT | \
KNOWN_FOLDER_FLAG.KF_FLAG_DONT_UNEXPAND | \
KNOWN_FOLDER_FLAG.KF_FLAG_CREATE | \
KNOWN_FOLDER_FLAG.KF_FLAG_DONT_VERIFY
return SHGetKnownFolderPath(KNOWNFOLDERID.FOLDERID_Documents, flags)
def get_reg_current_user_string_value(subkey, value_name):
import winreg
try:
my_key = winreg.OpenKeyEx(winreg.HKEY_CURRENT_USER, subkey)
except FileNotFoundError:
return None
try:
value, type_ = winreg.QueryValueEx(my_key, value_name)
if type_ == winreg.REG_SZ:
return value
else:
raise WindowsError("Unexpected type for value %s in registry: %i" % (valueName, type_))
except FileNotFoundError:
return None