Skip to content

Commit

Permalink
Merge pull request #1 from enthought/enh-load-resource
Browse files Browse the repository at this point in the history
Support basic library and resource loading
  • Loading branch information
cournape committed Feb 12, 2014
2 parents d5f2aba + 1fdd449 commit dc92f1e
Show file tree
Hide file tree
Showing 5 changed files with 273 additions and 13 deletions.
68 changes: 68 additions & 0 deletions mini_pywin32/_win32api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
from __future__ import absolute_import

import ctypes
from ctypes.wintypes import (
BOOL, DWORD, HANDLE, HMODULE, LONG, LPCWSTR, WCHAR, WORD, HRSRC,
HGLOBAL, LPVOID)

from .util import check_null, check_zero, function_factory, LONG_PTR

kernel32 = ctypes.windll.kernel32

ENUMRESTYPEPROC = ctypes.WINFUNCTYPE(BOOL, HMODULE, LONG, LONG_PTR)
ENUMRESNAMEPROC = ctypes.WINFUNCTYPE(BOOL, HMODULE, LONG, LONG, LONG_PTR)
ENUMRESLANGPROC = ctypes.WINFUNCTYPE(
BOOL, HMODULE, WCHAR, WCHAR, WORD, LONG_PTR)

_LoadLibraryEx = function_factory(
kernel32.LoadLibraryExW,
[LPCWSTR, HANDLE, DWORD],
HMODULE, check_null)

_FreeLibrary = function_factory(
kernel32.FreeLibrary,
[HMODULE],
BOOL,
check_zero)

_EnumResourceTypes = function_factory(
kernel32.EnumResourceTypesW,
[HMODULE, ENUMRESTYPEPROC, LONG_PTR],
BOOL,
check_zero)

_EnumResourceNames = function_factory(
kernel32.EnumResourceNamesW,
[HMODULE, DWORD, ENUMRESNAMEPROC, LONG_PTR],
BOOL,
check_zero)

_EnumResourceLanguages = function_factory(
kernel32.EnumResourceLanguagesW,
[HMODULE, LPCWSTR, LPCWSTR, ENUMRESLANGPROC, LONG_PTR],
BOOL,
check_zero)

_LoadResource = function_factory(
kernel32.LoadResource,
[HMODULE, HRSRC],
HGLOBAL,
check_zero)

_LockResource = function_factory(
kernel32.LockResource,
[HGLOBAL],
LPVOID,
check_null)

_FindResourceEx = function_factory(
kernel32.FindResourceExW,
[HMODULE, DWORD, DWORD, WORD],
HRSRC,
check_null)

_SizeofResource = function_factory(
kernel32.SizeofResource,
[HMODULE, HRSRC],
DWORD,
check_zero)
26 changes: 13 additions & 13 deletions mini_pywin32/_win32cred.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,19 @@ def _encode_password(password):
return unicode_str(password).encode("utf-16")

class CREDENTIAL(Structure):
_fields_ = [("Flags", DWORD),
("Type", DWORD),
("TargetName", c_wchar_p),
("Comment", c_wchar_p),
("LastWritten", FILETIME),
("CredentialBlobSize", DWORD),
("CredentialBlob", LPBYTE),
("Persist", DWORD),
("_DO_NOT_USE_AttributeCount", DWORD),
("__DO_NOT_USE_Attribute", c_void_p),
("TargetAlias", c_wchar_p),
("UserName", c_wchar_p),
]
_fields_ = [
("Flags", DWORD),
("Type", DWORD),
("TargetName", c_wchar_p),
("Comment", c_wchar_p),
("LastWritten", FILETIME),
("CredentialBlobSize", DWORD),
("CredentialBlob", LPBYTE),
("Persist", DWORD),
("_DO_NOT_USE_AttributeCount", DWORD),
("__DO_NOT_USE_Attribute", c_void_p),
("TargetAlias", c_wchar_p),
("UserName", c_wchar_p)]

PCREDENTIAL = POINTER(CREDENTIAL)

Expand Down
107 changes: 107 additions & 0 deletions mini_pywin32/tests/test_win32api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import sys
import unittest

import mini_pywin32.win32api
import win32api


class TestWin32API(unittest.TestCase):

def setUp(self):
self.handle = None

def tearDown(self):
if self.handle is not None:
self._free_library(win32api, self.handle)

def test_load_library_ex(self):
self.handle = self._load_library(win32api)
mini = self._load_library(mini_pywin32.win32api)
self.assertEqual(mini, self.handle)

with self.assertRaises(WindowsError):
mini_pywin32.win32api.LoadLibraryEx('ttt.dll', 0, 0x2)

def test_free_library(self):
self.handle = self._load_library(win32api)
self.assertIsNone(self._free_library(win32api, self.handle))
self.assertNotEqual(
self._free_library(mini_pywin32.win32api, self.handle), 0)

with self.assertRaises(WindowsError):
self._free_library(mini_pywin32.win32api, -3)

def test_enum_resource_types(self):
self.handle = self._load_library(win32api)
original = self._enum_resource_types(win32api, self.handle)
mini = self._enum_resource_types(mini_pywin32.win32api, self.handle)
self.assertEqual(mini, original)

with self.assertRaises(WindowsError):
mini_pywin32.win32api.EnumResourceTypes(-3)

def test_enum_resource_names(self):
self.handle = self._load_library(win32api)
resource_types = self._enum_resource_types(win32api, self.handle)

for resource_type in resource_types:
original = self._enum_resource_names(
win32api, self.handle, resource_type)
mini = self._enum_resource_names(
mini_pywin32.win32api, self.handle, resource_type)
self.assertEqual(mini, original)

with self.assertRaises(WindowsError):
mini_pywin32.win32api.EnumResourceNames(2, 3)


def test_enum_resource_languages(self):
handle = self._load_library(win32api)
resource_types = self._enum_resource_types(win32api, handle)

for resource_type in resource_types:
resource_names = self._enum_resource_names(
win32api, handle, resource_type)
for resource_name in resource_names:
resource_languages = self._enum_resource_languages(
win32api, handle, resource_type, resource_name)
for resource_language in resource_languages:
original = self._load_resource(
win32api, handle,
resource_type, resource_name,
resource_language)
mini = self._load_resource(
mini_pywin32.win32api, handle,
resource_type, resource_name,
resource_language)
self.assertEqual(mini, original)

with self.assertRaises(WindowsError):
mini_pywin32.win32api.LoadResource(
handle, resource_type, resource_name, 3)

def _load_library(self, module):
# backward shim for win32api module which does not export
# LOAD_LIBRARY_AS_DATAFILE
LOAD_LIBRARY_AS_DATAFILE = getattr(
module, "LOAD_LIBRARY_AS_DATAFILE", 0x2)
return module.LoadLibraryEx(
sys.executable, 0, LOAD_LIBRARY_AS_DATAFILE)

def _free_library(self, module, handle):
return module.FreeLibrary(handle)

def _enum_resource_types(self, module, handle):
return module.EnumResourceTypes(handle)

def _enum_resource_names(self, module, handle, resource_type):
return module.EnumResourceNames(handle, resource_type)

def _enum_resource_languages(self, module, handle, resource_type, name):
return module.EnumResourceLanguages(handle, resource_type, name)

def _load_resource(
self, module, handle, resource_type,
resource_name, resource_language):
return module.LoadResource(
handle, resource_type, resource_name, resource_language)
26 changes: 26 additions & 0 deletions mini_pywin32/util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import ctypes
from ctypes import WinError

if ctypes.sizeof(ctypes.c_long) == ctypes.sizeof(ctypes.c_void_p):
LONG_PTR = ctypes.c_long
elif ctypes.sizeof(ctypes.c_longlong) == ctypes.sizeof(ctypes.c_void_p):
LONG_PTR = ctypes.c_longlong


def function_factory(
function, argument_types, return_type=None, error_checking=None):
function.argtypes = argument_types
function.restype = return_type
if error_checking is not None:
function.errcheck = error_checking
return function

def check_null(result, func, arguments, *args):
if result is None:
raise WinError()
return result

def check_zero(result, func, arguments, *args):
if result == 0:
raise WinError()
return result
59 changes: 59 additions & 0 deletions mini_pywin32/win32api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
from __future__ import absolute_import

from . import _win32api, _win32cred

LOAD_LIBRARY_AS_DATAFILE = 0x2


def LoadLibraryEx(FileName, handle, flags):
if not handle == 0:
raise ValueError("handle != 0 not supported")
return _win32api._LoadLibraryEx(FileName, 0, flags)


def EnumResourceTypes(hModule):
resource_types = []

def callback(hModule, typeid, param):
resource_types.append(typeid)
return True

_win32api._EnumResourceTypes(
hModule, _win32api.ENUMRESTYPEPROC(callback), 0)
return resource_types


def EnumResourceNames(hModule, type_):
resource_names = []

def callback(hModule, type_, type_name, param):
resource_names.append(type_name)
return True

_win32api._EnumResourceNames(
hModule, type_, _win32api.ENUMRESNAMEPROC(callback), 0)
return resource_names


def EnumResourceLanguages(hModule, type_, name):
resource_languages = []

def callback(hModule, type_name, res_name, language_id, param):
resource_languages.append(language_id)
return True

_win32api._EnumResourceLanguages(
hModule, type_, name, _win32api.ENUMRESLANGPROC(callback), 0)
return resource_languages


def LoadResource(hModule, type_, name, language):
hrsrc = _win32api._FindResourceEx(hModule, type_, name, language)
size = _win32api._SizeofResource(hModule, hrsrc)
hglob = _win32api._LoadResource(hModule, hrsrc)
pointer = _win32api._LockResource(hglob)
return _win32cred._PyString_FromStringAndSize(pointer, size)


def FreeLibrary(hModule):
return _win32api._FreeLibrary(hModule)

0 comments on commit dc92f1e

Please sign in to comment.