On Sun, Mar 5, 2017 at 12:16 AM, Kurt Eilander wrote:
>
> I'm having another problem. I'm wanting to get the size of a dll resource,
> but...
>
> When I do:
> try:
> hLib=win32api.GetModuleHandle(fileName)
> except:
> hLib=win32api.LoadLibrary(fileName)
> if hLib==None:
> raise WindowsError('File not found, '+fileName)
> hResInfo=ctypes.windll.kernel32.FindResourceW(hLib,index,type)
> size=ctypes.windll.kernel32.SizeofResource(hLib,hResInfo)
>
> It throws:
> hResInfo=ctypes.windll.kernel32.FindResourceW(hLib,index,type)
> ctypes.ArgumentError: argument 1: :
> long int too long to convert
>
> Almost like ctypes doesn't like the win32api handle.
>
> My machine is 64 bit. Is that what ctypes is not liking? Is there a way
> around it?
The default conversion for integer arguments is to a 32-bit C int. The
implementation calls PyLong_AsLong, for which a 64-bit address can
raise an overflow exception on Windows since a C long is always 32-bit
on this platform. You're lucky to get an exception. The problem is
worse on Unix systems that have a 64-bit C long. The conversion
doesn't overflow, but ctypes itself silently casts the address to a
32-bit int. Invariably this causes a segfault, either directly or
indirectly due to stack or heap corruption.
It looks like you're also not setting restype to a pointer type for
FindResourceW. Like with parameters, the default integer conversion
type for a function result is a 32-bit C int. A 64-bit result will be
silently truncated on Windows as well. Kernel and User handles never
exceed 32-bit values, but don't assume that's true of all handles.
HMODULE handles break this rule, as do others. Always assume a handle
type requires the full range of a pointer.
Here are some general suggestions. Use ctypes.WinDLL instead of
ctypes.windll (the latter was a bad design for multiple reasons). Load
the library with the option use_last_error=True, unless you're working
with NT or COM libraries that return NTSTATUS or HRESULT values.
Always set the function prototype -- at least argtypes; restype if the
function returns a pointer type; and preferably an errcheck function
that raises idiomatic exceptions.
For example:
import winerror
import win32api
import ctypes
from ctypes import wintypes
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
def _check_zero(result, func, args):
if not result:
raise ctypes.WinError(ctypes.get_last_error())
return args
kernel32.FindResourceW.errcheck = _check_zero
kernel32.FindResourceW.restype = wintypes.HRSRC
kernel32.FindResourceW.argtypes = (
wintypes.HMODULE, # _In_opt_ hModule
wintypes.LPCWSTR, # _In_ lpName
wintypes.LPCWSTR) # _In_ lpType
kernel32.LoadResource.errcheck = _check_zero
kernel32.LoadResource.restype = wintypes.HGLOBAL
kernel32.LoadResource.argtypes = (
wintypes.HMODULE, # _In_opt_ hModule
wintypes.HRSRC) # _In_ hResInfo
kernel32.SizeofResource.errcheck = _check_zero
kernel32.SizeofResource.restype = wintypes.DWORD
kernel32.SizeofResource.argtypes = (
wintypes.HMODULE, # _In_opt_ hModule
wintypes.HRSRC) # _In_ hResInfo
kernel32.LockResource.restype = wintypes.LPVOID
kernel32.LockResource.argtypes = (
wintypes.HGLOBAL,) # _In_ hResData
def get_resource(filename, index, rtype):
try:
hLib = win32api.GetModuleHandle(filename)
except win32api.error as e:
if e.winerror != winerror.ERROR_MOD_NOT_FOUND:
raise
hLib = win32api.LoadLibrary(filename)
index = wintypes.LPCWSTR(index) # MAKEINTRESOURCE
rtype = wintypes.LPCWSTR(rtype)
hResInfo = kernel32.FindResourceW(hLib, index, rtype)
hRes = kernel32.LoadResource(hLib, hResInfo)
size = kernel32.SizeofResource(hLib, hResInfo)
addr = kernel32.LockResource(hRes)
return ctypes.string_at(addr, size)
if __name__ == '__main__':
RT_MANIFEST = 24
manifest = get_resource(None, 1, RT_MANIFEST).decode('utf-8')
print(manifest)
The above demo prints the embedded manifest from python.exe. Of
course, it would be a lot simpler to use win32api.LoadResource [1]:
manifest = win32api.LoadResource(None, RT_MANIFEST, 1).decode('utf-8')
[1]:
http://docs.activestate.com/activepython/3.4/pywin32/win32api__LoadResource_meth.html
___
python-win32 mailing list
python-win32@python.org
https://mail.python.org/mailman/listinfo/python-win32