Issue #27932: Fixes memory leak in platform.win32_ver()

This commit is contained in:
Steve Dower 2016-09-09 18:04:26 -07:00
commit 1588a3b377
2 changed files with 36 additions and 30 deletions

View File

@ -497,57 +497,61 @@ _WIN32_SERVER_RELEASES = {
(6, None): "post2012ServerR2", (6, None): "post2012ServerR2",
} }
if sys.platform == 'win32':
import ctypes
import ctypes.wintypes
class VS_FIXEDFILEINFO(ctypes.Structure):
_fields_ = [
("dwSignature", ctypes.wintypes.DWORD),
("dwStrucVersion", ctypes.wintypes.DWORD),
("dwFileVersionMS", ctypes.wintypes.DWORD),
("dwFileVersionLS", ctypes.wintypes.DWORD),
("dwProductVersionMS", ctypes.wintypes.DWORD),
("dwProductVersionLS", ctypes.wintypes.DWORD),
("dwFileFlagsMask", ctypes.wintypes.DWORD),
("dwFileFlags", ctypes.wintypes.DWORD),
("dwFileOS", ctypes.wintypes.DWORD),
("dwFileType", ctypes.wintypes.DWORD),
("dwFileSubtype", ctypes.wintypes.DWORD),
("dwFileDateMS", ctypes.wintypes.DWORD),
("dwFileDateLS", ctypes.wintypes.DWORD),
]
P_VS_FIXEDFILEINFO = ctypes.POINTER(VS_FIXEDFILEINFO)
def _get_real_winver(maj, min, build): def _get_real_winver(maj, min, build):
if maj < 6 or (maj == 6 and min < 2): if maj < 6 or (maj == 6 and min < 2):
return maj, min, build return maj, min, build
from ctypes import (c_buffer, POINTER, byref, create_unicode_buffer, kernel32 = ctypes.WinDLL('kernel32')
Structure, WinDLL)
from ctypes.wintypes import DWORD, HANDLE
class VS_FIXEDFILEINFO(Structure):
_fields_ = [
("dwSignature", DWORD),
("dwStrucVersion", DWORD),
("dwFileVersionMS", DWORD),
("dwFileVersionLS", DWORD),
("dwProductVersionMS", DWORD),
("dwProductVersionLS", DWORD),
("dwFileFlagsMask", DWORD),
("dwFileFlags", DWORD),
("dwFileOS", DWORD),
("dwFileType", DWORD),
("dwFileSubtype", DWORD),
("dwFileDateMS", DWORD),
("dwFileDateLS", DWORD),
]
kernel32 = WinDLL('kernel32')
version = WinDLL('version')
# We will immediately double the length up to MAX_PATH, but the # We will immediately double the length up to MAX_PATH, but the
# path may be longer, so we retry until the returned string is # path may be longer, so we retry until the returned string is
# shorter than our buffer. # shorter than our buffer.
name_len = actual_len = 130 name_len = actual_len = 130
while actual_len == name_len: while actual_len == name_len:
name_len *= 2 name_len *= 2
name = create_unicode_buffer(name_len) name = ctypes.create_unicode_buffer(name_len)
actual_len = kernel32.GetModuleFileNameW(HANDLE(kernel32._handle), actual_len = kernel32.GetModuleFileNameW(
name, len(name)) ctypes.wintypes.HANDLE(kernel32._handle),
name, len(name)
)
if not actual_len: if not actual_len:
return maj, min, build return maj, min, build
version = ctypes.WinDLL('version')
size = version.GetFileVersionInfoSizeW(name, None) size = version.GetFileVersionInfoSizeW(name, None)
if not size: if not size:
return maj, min, build return maj, min, build
ver_block = c_buffer(size) ver_block = ctypes.c_buffer(size)
if (not version.GetFileVersionInfoW(name, None, size, ver_block) or if (not version.GetFileVersionInfoW(name, None, size, ver_block) or
not ver_block): not ver_block):
return maj, min, build return maj, min, build
pvi = POINTER(VS_FIXEDFILEINFO)() pvi = P_VS_FIXEDFILEINFO()
if not version.VerQueryValueW(ver_block, "", byref(pvi), byref(DWORD())): if not version.VerQueryValueW(ver_block, "",
ctypes.byref(pvi), ctypes.byref(ctypes.wintypes.DWORD())):
return maj, min, build return maj, min, build
maj = pvi.contents.dwProductVersionMS >> 16 maj = pvi.contents.dwProductVersionMS >> 16

View File

@ -125,6 +125,8 @@ Core and Builtins
Library Library
------- -------
- Issue #27932: Fixes memory leak in platform.win32_ver()
- Issue #14977: mailcap now respects the order of the lines in the mailcap - Issue #14977: mailcap now respects the order of the lines in the mailcap
files ("first match"), as required by RFC 1542. Patch by Michael Lazar. files ("first match"), as required by RFC 1542. Patch by Michael Lazar.