[PATCH 1 of 5] port win32.py to using the Python ctypes library

Patrick Mézard pmezard at gmail.com
Sun Feb 13 07:53:12 CST 2011


Le 13/02/11 14:07, Adrian Buehlmann a écrit :
> On 2011-02-13 12:39, Patrick Mézard wrote:
>> Le 08/02/11 17:52, Adrian Buehlmann a écrit :
>>> # HG changeset patch
>>> # User Adrian Buehlmann <adrian at cadifra.com>
>>> # Date 1297121623 -3600
>>> # Node ID 3ba4920422e9abcdc8b8634c5c12c68051286a8c
>>> # Parent  69e69b131458023d21ec40aa48fc5299e43ce69b
>>> port win32.py to using the Python ctypes library

[...]

>>> +                adv.RegCloseKey(kh.value)
>>>  
>>>  def system_rcpath_win32():
>>>      '''return default os-specific hgrc search path'''
>>> -    filename = win32api.GetModuleFileName(0)
>>> +    rcpath = []
>>> +    size = 600
>>> +    buf = ctypes.create_string_buffer(size + 1)
>>> +    len = _kernel32.GetModuleFileNameA(None, ctypes.byref(buf), size)
>>> +    if not len:
>>
>> This should check the case where buf is too small, testing if len == size should be good enough.
>>
>>   http://msdn.microsoft.com/en-us/library/ms683197(VS.85).aspx
> 
> Sounds a bit difficult to me to put an exe in a path location with a path length
>> 600 on a file system if the OS' maximum path length is 260.
> 
> Can an exe be started from a path longer than 260?
> 
> After all, the buffer has a size of 600...
> 
> But adding a check for truncation is certainly an improvement and won't harm.
> 
> FWIW, GetModuleFileNameA will never write more than size chars, so it's not like
> we are talking about a potential buffer overrun case here (truncation at worst).

I was just worried about NUL termination. It is not clear to me whether ctypes.create_string_buffer() zero-initialize the returned buffer (it is not mentioned in the doc) and I don't know what happens if we try to read it as a string while no NUL terminated. Avoiding it entirely just sound less work to me than trying to answer these questions.

> (although it's quite beyond comprehension why Microsoft returns success on
> GetModuleFileNameA if the target buffer is too small)

Yes, I felt the need to skim the MSDN entry (at least the "Return Value" part) for every function you wrapped. Win32 API is such a minefield...

[...]

>>> +_SIGNAL_HANDLER = ctypes.WINFUNCTYPE(_BOOL, _DWORD)
>>> +_signal_handler = []
>>>  
>>>  def set_signal_handler_win32():
>>> -    """Register a termination handler for console events including
>>> +    '''Register a termination handler for console events including
>>>      CTRL+C. python signal handlers do not work well with socket
>>>      operations.
>>> -    """
>>> +    '''
>>>      def handler(event):
>>> -        win32process.ExitProcess(1)
>>> -    win32api.SetConsoleCtrlHandler(handler)
>>> +        _kernel32.ExitProcess(1)
>>> +
>>> +    if _signal_handler:
>>> +        return # already registered
>>
>> (This behaviour change could have gone in another patch too, unless the ctypes version does behave differently than the pywin32 one.)
> 
> What behavior change?

The part about not-registering the handler more than once. Perhaps pywin32 was doing it. When reading the code, it just appeared like an additional feature, and I am not sure it is completely necessary given the handler already ExitProcess(). But I may be missing something.

--
Patrick Mézard


More information about the Mercurial-devel mailing list