Last active
August 27, 2020 04:34
-
-
Save polyvertex/a5e40122e1835d9efa9b to your computer and use it in GitHub Desktop.
A wrapper over ctypes for the Windows API
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ctypes as ct | |
from ctypes.wintypes import * | |
import uuid | |
def has_func(ctypes_dll, func_name): | |
if hasattr(ctypes_dll, func_name): | |
return func_name | |
if not func_name.endswith("W") and hasattr(ctypes_dll, func_name + "W"): | |
return func_name + "W" | |
return None | |
def declare_func(*args, **kwargs): | |
return declare_func2(*args, **kwargs)[0] | |
def declare_func2(ctypes_dll, func_name, ret=None, arg=[]): | |
# do not fail if the function is not supported by the os | |
func_name = has_func(ctypes_dll, func_name) | |
if not func_name: | |
return None, None | |
# encapsulated *arg* in a list if needed | |
if isinstance(arg, tuple): | |
arg = list(arg) | |
elif not isinstance(arg, list): | |
arg = [arg] | |
# declare function in ctypes' namespace | |
func = getattr(ctypes_dll, func_name) | |
func.argtypes = arg | |
if ret is not None: | |
func.restype = ret | |
return func, func_name | |
def declare_global_func(*args, **kwargs): | |
func, name = declare_func2(*args, **kwargs) | |
if func: | |
globals()[name] = func | |
return func | |
return None | |
def ZeroMemory(ctypes_obj): | |
ct.memset(ct.addressof(ctypes_obj), 0, ct.sizeof(ctypes_obj)) | |
LRESULT = LPARAM | |
LONG_PTR = LPARAM | |
ULONG_PTR = WPARAM | |
PVOID = ct.c_void_p | |
class COPYDATASTRUCT(ct.Structure): | |
_fields_ = [("dwData", ULONG_PTR), | |
("cbData", DWORD), | |
("lpData", PVOID)] | |
class GUID(Structure): | |
_fields_ = [ | |
("Data1", DWORD), | |
("Data2", WORD), | |
("Data3", WORD), | |
("Data4", BYTE * 8)] | |
def __init__(self, uuidstr): | |
super().__init__(self) | |
(self.Data1, self.Data2, self.Data3, self.Data4[0], self.Data4[1], | |
rest) = uuid.UUID(uuidstr).fields | |
for i in range(2, 8): | |
self.Data4[i] = rest >> (8 - i - 1) * 8 & 0xff | |
class WNDCLASSEXW(ct.Structure): | |
_fields_ = [("cbSize", UINT), | |
("style", UINT), | |
("lpfnWndProc", WNDPROCTYPE), | |
("cbClsExtra", ct.c_int), | |
("cbWndExtra", ct.c_int), | |
("hInstance", HINSTANCE), | |
("hIcon", HICON), | |
("hCursor", HANDLE), | |
("hBrush", HBRUSH), | |
("lpszMenuName", LPCWSTR), | |
("lpszClassName", LPCWSTR), | |
("hIconSm", HICON)] | |
WNDPROCTYPE = ct.WINFUNCTYPE(LRESULT, HWND, UINT, WPARAM, LPARAM) | |
WM_QUIT = 0x12 | |
WM_COPYDATA = 0x4A | |
WM_COMMAND = 0x0111 | |
WM_USER = 0x0400 | |
WAIT_TIMEOUT = 258 | |
GWLP_USERDATA = -21 | |
FOLDERID_AccountPictures = "{008ca0b1-55b4-4c56-b8a8-4de4b299d3be}" # %APPDATA%\Microsoft\Windows\AccountPictures | |
FOLDERID_CommonStartMenu = "{a4115719-d62e-491d-aa7c-e74b8be3b067}" # %ALLUSERSPROFILE%\Microsoft\Windows\Start Menu | |
FOLDERID_CommonStartup = "{82a5ea35-d9cd-47c5-9629-e15d2f714e6e}" # %ALLUSERSPROFILE%\Microsoft\Windows\Start Menu\Programs\StartUp | |
FOLDERID_Desktop = "{b4bfcc3a-db2c-424c-b029-7fe99a87c641}" # %USERPROFILE%\Desktop | |
FOLDERID_Documents = "{fdd39ad0-238f-46af-adb4-6c85480369c7}" # %USERPROFILE%\Documents | |
FOLDERID_Downloads = "{374de290-123f-4565-9164-39c4925e467b}" # %USERPROFILE%\Downloads | |
FOLDERID_LocalAppData = "{f1b32785-6fba-4fcf-9d55-7b8e7f157091}" # %LOCALAPPDATA% (%USERPROFILE%\AppData\Local) | |
FOLDERID_LocalAppDataLow = "{A520A1A4-1780-4FF6-BD18-167343C5AF16}" # %USERPROFILE%\AppData\LocalLow | |
FOLDERID_Profile = "{5e6c858f-0e22-4760-9afe-ea3317b67173}" # %USERPROFILE% (%SystemDrive%\Users\%USERNAME%) | |
FOLDERID_ProgramFiles = "{905e63b6-c1bf-494e-b29c-65b732d3d21a}" # %ProgramFiles% | |
FOLDERID_ProgramFilesX64 = "{6d809377-6af0-444b-8957-a3773f02200e}" # %ProgramFiles% | |
FOLDERID_ProgramFilesX86 = "{7c5a40ef-a0fb-4bfc-874a-c0f2e0b9fa8e}" # %ProgramFiles(x86)% | |
FOLDERID_RoamingAppData = "{3eb685db-65f9-4cf6-a03a-e3ef65729f3d}" # %APPDATA% (%USERPROFILE%\AppData\Roaming) | |
FOLDERID_StartMenu = "{625b53c3-ab48-4ec1-ba1f-a1ef4146fc19}" # %APPDATA%\Microsoft\Windows\Start Menu | |
FOLDERID_Startup = "{b97d20bb-f46a-4c97-ba10-5e3608430854}" # %APPDATA%\Microsoft\Windows\Start Menu\Programs\StartUp | |
FOLDERID_UserProgramFiles = "{5cd7aee2-2219-4a67-b85d-6c9ce15660cb}" # %LOCALAPPDATA%\Programs | |
FOLDERID_Windows = "{f38bf404-1d43-42f2-9305-67de0b28fc23}" # %windir% | |
kernel32 = ct.windll.kernel32 | |
user32 = ct.windll.user32 | |
shell32 = ct.windll.shell32 | |
declare_global_func(kernel32, "GetLastError", ret=DWORD) | |
declare_global_func(kernel32, "GetModuleHandleW", ret=HMODULE, arg=[LPCWSTR]) | |
declare_global_func(kernel32, "SetLastError", arg=[DWORD]) | |
declare_global_func(user32, "ChangeWindowMessageFilterEx", ret=BOOL, | |
arg=[HWND, UINT, DWORD, ct.c_void_p]) | |
declare_global_func(user32, "CreateWindowExW", ret=HWND, arg=[ | |
DWORD, LPCWSTR, LPCWSTR, DWORD, ct.c_int, ct.c_int, ct.c_int, ct.c_int, | |
HWND, HANDLE, HINSTANCE, LPVOID]) | |
declare_global_func(user32, "DefWindowProcW", ret=LRESULT, | |
arg=[HWND, UINT, WPARAM, LPARAM]) | |
declare_global_func(user32, "DestroyWindow", ret=BOOL, arg=[HWND]) | |
declare_global_func(user32, "DispatchMessageW", ret=LRESULT, arg=[LPMSG]) | |
declare_global_func(user32, "FindWindowW", ret=HWND, arg=[LPCWSTR, LPCWSTR]) | |
declare_global_func(user32, "GetClassInfoExW", ret=BOOL, | |
arg=[HANDLE, LPCWSTR, ct.POINTER(WNDCLASSEXW)]) | |
declare_global_func(user32, "GetWindowLongPtrW", ret=LONG_PTR, | |
arg=[HWND, ct.c_int]) | |
declare_global_func(user32, "MsgWaitForMultipleObjects", ret=DWORD, | |
arg=[DWORD, ct.POINTER(HANDLE), BOOL, DWORD, DWORD]) | |
declare_global_func(user32, "PeekMessageW", ret=BOOL, | |
arg=[LPMSG, HWND, UINT, UINT, UINT]) | |
declare_global_func(user32, "RegisterClassExW", ret=ATOM, | |
arg=[ct.POINTER(WNDCLASSEXW)]) | |
declare_global_func(user32, "SendMessageW", ret=LRESULT, | |
arg=[HWND, UINT, WPARAM, LPARAM]) | |
declare_global_func(user32, "SetWindowLongPtrW", ret=LONG_PTR, | |
arg=[HWND, ct.c_int, LONG_PTR]) | |
declare_global_func(user32, "TranslateMessage", ret=BOOL, arg=[LPMSG]) | |
declare_global_func(shell32, "SHGetKnownFolderPath", ret=ct.HRESULT, | |
arg=[ct.POINTER(GUID), DWORD, HANDLE, PWSTR]) | |
def get_known_folder_path(known_folder_guidstr): | |
guid = GUID(known_folder_guidstr) | |
path_ptr = ct.c_wchar_p() | |
res = SHGetKnownFolderPath(ct.byref(guid), 0, None, ct.byref(path_ptr)) | |
if res: | |
raise OSError(0, "SHGetKnownFolderPath('{}') failed (code {})".format(known_folder_guidstr, res), None, res) | |
return path_ptr.value |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment