-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from enthought/enh-load-resource
Support basic library and resource loading
- Loading branch information
Showing
5 changed files
with
273 additions
and
13 deletions.
There are no files selected for viewing
This file contains 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
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) |
This file contains 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
This file contains 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
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) |
This file contains 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
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 |
This file contains 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
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) |