Re: [python-win32] win32api handle incompatible with ctypes?

2017-03-04 Thread eryk sun
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


[python-win32] win32api handle incompatible with ctypes?

2017-03-04 Thread Kurt Eilander

Hey all,

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: 'exceptions.OverflowError'>: 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?


-Kurt
___
python-win32 mailing list
python-win32@python.org
https://mail.python.org/mailman/listinfo/python-win32