python, ctypes and GetIconInfo issue

mymyxin at gmail.com mymyxin at gmail.com
Fri May 6 09:36:03 EDT 2016


Hello eryk sun,
first of all thank you very much, really appreciate your help.
Please be informed that I'm a python beginner, so forgive me if
my following questions sound stupid (also I'm not a native speaker).

> Please avoid windll. It caches the loaded library, which in turn 
> caches function pointers. So all packages that use windll.user32 are 
> potentially stepping on each others' toes with mutually incompatible 
> function prototypes. It also doesn't allow configuring 
> use_last_error=True to enable ctypes.get_last_error() for WinAPI 
> function calls. 
I assume you are referring to this block of code

    GetIconInfo = windll.user32.GetIconInfo
    GetIconInfo.argtypes   = [HICON, POINTER(ICONINFO)]
    GetIconInfo.restype    = BOOL
    GetIconInfo.errcheck   = ErrorIfZero

where as you use

    user32 = ctypes.WinDLL('user32', use_last_error=True) 
    user32.GetIconInfoExW.errcheck = check_bool 
    user32.GetIconInfoExW.restype = wintypes.BOOL 
    user32.GetIconInfoExW.argtypes = ( 
        wintypes.HICON, # _In_  hIcon 
        PICONINFOEX,)   # _Out_ piconinfoex 
        
I've checked ctype docu included in python but don't find any hint about your concerns.
May I ask you, do you know additional documents/sites which I can use to get a better understanding
about caching issue? Or did I miss something from used documentation?

> The attribute name is "_fields_", not "__fields__", so you haven't 
> actually defined any fields and sizeof(ICONINFO) is 0. When you pass 
> this empty struct to GetIconInfo, it potentially overwrites and 
> corrupts existing data on the heap that can lead to a crash later on. 

Ahhh, typically me. Thank you for pointing to it.

> Here's the setup I created to test GetIconInfo and GetIconInfoEx. 
> Maybe you can reuse some of this code, but if you're using XP this 
> won't work as written because GetIconInfoEx was added in Vista. 

> Note the use of a __del__ finalizer to call DeleteObject on the 
> bitmaps. Otherwise, in a real application, calling GetIconInfo would 
> leak memory. 

Oh, you answered already an upcoming question I guess, thank you ;-)

> Using __del__ is convenient, but note that you can't 
> reuse an instance without manually calling DeleteObject on the 
> bitmaps. 
Don't understand this. Isn't this covered by your example in base class?

    class ICONINFO_BASE(ctypes.Structure): 
        def __del__(self, gdi32=gdi32): 
            if self.hbmMask: 
                gdi32.DeleteObject(self.hbmMask) 
                self.hbmMask = None 
            if self.hbmColor: 
                gdi32.DeleteObject(self.hbmColor) 
                self.hbmColor = None 
                
If I would do somthing like

    iconinfoex = ICONINFOEX()
    iconinfoex = None
    
DeleteObject would be called once None gets assigned, wouldn't it?

Again, thank you very much.
Hubert



More information about the Python-list mailing list