mirror of
https://github.com/hakril/PythonForWindows
synced 2026-06-08 14:31:45 +00:00
Added symbol sample + SymbolDebugger
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
import argparse
|
||||
import os
|
||||
|
||||
import windows
|
||||
import windows.debug
|
||||
import windows.test
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(prog=__file__, formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||
parser.add_argument('--dbghelp', help='The path of DBG help to use (default use env:PFW_DBGHELP_PATH)')
|
||||
args = parser.parse_args()
|
||||
print(args)
|
||||
|
||||
if args.dbghelp:
|
||||
symbols.set_dbghelp_path(args.dbghelp)
|
||||
else:
|
||||
if "PFW_DBGHELP_PATH" not in os.environ:
|
||||
print("Not dbghelp path given and no environ var 'PFW_DBGHELP_PATH' sample may fail")
|
||||
|
||||
|
||||
class MyInfoBP(windows.debug.Breakpoint):
|
||||
COUNT = 0
|
||||
def trigger(self, dbg, exc):
|
||||
cursym = dbg.current_resolver[exc.ExceptionRecord.ExceptionAddress]
|
||||
print("Breakpoint triggered at: {0}".format(cursym))
|
||||
print(repr(cursym))
|
||||
MyInfoBP.COUNT += 1
|
||||
if MyInfoBP.COUNT == 4:
|
||||
print("Quitting")
|
||||
dbg.current_process.exit()
|
||||
print("")
|
||||
|
||||
dbg = windows.debug.SymbolDebugger.debug(r"c:\windows\system32\notepad.exe")
|
||||
dbg.add_bp(MyInfoBP("kernelbase!CreateFileInternal+2"))
|
||||
dbg.add_bp(MyInfoBP("ntdll!LdrpInitializeProcess"))
|
||||
dbg.loop()
|
||||
@@ -0,0 +1,50 @@
|
||||
import os
|
||||
import argparse
|
||||
|
||||
import windows
|
||||
import windows.test
|
||||
import windows.generated_def as gdef
|
||||
from windows.debug import symbols
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(prog=__file__, formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||
parser.add_argument('--dbghelp', help='The path of DBG help to use (default use env:PFW_DBGHELP_PATH)')
|
||||
args = parser.parse_args()
|
||||
print(args)
|
||||
|
||||
if args.dbghelp:
|
||||
symbols.set_dbghelp_path(args.dbghelp)
|
||||
else:
|
||||
if "PFW_DBGHELP_PATH" not in os.environ:
|
||||
print("Not dbghelp path given and no environ var 'PFW_DBGHELP_PATH' sample may fail")
|
||||
|
||||
|
||||
if windows.current_process.bitness == 32:
|
||||
target = windows.test.pop_proc_32()
|
||||
else:
|
||||
target = windows.test.pop_proc_64()
|
||||
|
||||
print("Target is {0}".format(target))
|
||||
sh = symbols.ProcessSymbolHandler(target)
|
||||
import time;time.sleep(0.1) # Just wait for the process initialisation
|
||||
sh.refresh() # Refresh symbol list (Only meaningful for ProcessSymbolHandler)
|
||||
|
||||
print("Some loaded modules are:".format())
|
||||
for sm in sh.modules[:3]:
|
||||
print(" * {0}".format(sm))
|
||||
|
||||
createserv = sh["advapi32!CreateServiceEx"]
|
||||
|
||||
print("")
|
||||
TEST_FUNCTION = "advapi32!CreateServiceEx"
|
||||
print("Resolving function <{0}>".format(TEST_FUNCTION))
|
||||
createserv = sh[TEST_FUNCTION]
|
||||
print("Symbol found !")
|
||||
print(" * __repr__: {0!r}".format(createserv))
|
||||
print(" * __str__: {0}".format(createserv))
|
||||
print(" * addr: {0:#x}".format(createserv.addr))
|
||||
print(" * name: {0}".format(createserv.name))
|
||||
print(" * fullname: {0}".format(createserv.fullname))
|
||||
print(" * module: {0}".format(createserv.module))
|
||||
|
||||
target.exit()
|
||||
@@ -0,0 +1,28 @@
|
||||
import argparse
|
||||
import os
|
||||
|
||||
import windows
|
||||
import windows.debug.symbols as symbols
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(prog=__file__, formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||
parser.add_argument('pattern')
|
||||
parser.add_argument('file', help="The PE file to load")
|
||||
parser.add_argument('--addr', type=lambda x: int(x, 0), default=0, help="The load address of the PE")
|
||||
parser.add_argument('--tag', type=lambda x: int(x, 0), default=0)
|
||||
parser.add_argument('--dbghelp', help='The path of DBG help to use (default use env:PFW_DBGHELP_PATH)')
|
||||
|
||||
args = parser.parse_args()
|
||||
if args.dbghelp:
|
||||
symbols.set_dbghelp_path(args.dbghelp)
|
||||
else:
|
||||
if "PFW_DBGHELP_PATH" not in os.environ:
|
||||
print("Not dbghelp path given and no environ var 'PFW_DBGHELP_PATH' sample may fail")
|
||||
|
||||
|
||||
sh = symbols.VirtualSymbolHandler()
|
||||
mod = sh.load_file(path=args.file, addr=args.addr)
|
||||
res = sh.search(args.pattern, mod=mod, tag=args.tag)
|
||||
print("{0} symbols found:".format(len(res)))
|
||||
for sym in res:
|
||||
print(" * {0!r}".format(sym))
|
||||
@@ -0,0 +1,59 @@
|
||||
import os
|
||||
import windows
|
||||
import windows.generated_def as gdef
|
||||
from windows.debug import symbols
|
||||
import argparse
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(prog=__file__, formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||
parser.add_argument('--dbghelp', help='The path of DBG help to use (default use env:PFW_DBGHELP_PATH)')
|
||||
args = parser.parse_args()
|
||||
print(args)
|
||||
|
||||
if args.dbghelp:
|
||||
symbols.set_dbghelp_path(args.dbghelp)
|
||||
else:
|
||||
if "PFW_DBGHELP_PATH" not in os.environ:
|
||||
print("Not dbghelp path given and no environ var 'PFW_DBGHELP_PATH' sample may fail")
|
||||
|
||||
|
||||
symbols.engine.options = 0 # Disable defered load
|
||||
sh = symbols.VirtualSymbolHandler()
|
||||
|
||||
ntmod = sh.load_file(r"c:\windows\system32\ntdll.dll", addr=0x420000)
|
||||
|
||||
print("Ntdll module is: {0}".format(ntmod))
|
||||
print(" * name = {0}".format(ntmod.name))
|
||||
print(" * addr = {0:#x}".format(ntmod.addr))
|
||||
print(" * path = {0:}".format(ntmod.path))
|
||||
print(" * type = {0:}".format(ntmod.type))
|
||||
print(" * pdb = {0:}".format(ntmod.pdb))
|
||||
|
||||
print("")
|
||||
TEST_FUNCTION = "LdrLoadDll"
|
||||
print("Resolving function <{0}>".format(TEST_FUNCTION))
|
||||
loaddll = sh["ntdll!" + TEST_FUNCTION]
|
||||
print("Symbol found !")
|
||||
print(" * __repr__: {0!r}".format(loaddll))
|
||||
print(" * __str__: {0}".format(loaddll))
|
||||
print(" * addr: {0:#x}".format(loaddll.addr))
|
||||
print(" * name: {0}".format(loaddll.name))
|
||||
print(" * fullname: {0}".format(loaddll.fullname))
|
||||
print(" * module: {0}".format(loaddll.module))
|
||||
|
||||
print("")
|
||||
print("Loading kernelbase")
|
||||
kbasemod = sh.load_file(r"c:\windows\system32\kernelbase.dll", addr=0x1230000)
|
||||
print("Loaded modules are: {0}".format(sh.modules))
|
||||
LOOKUP_ADDR = 0x1231242
|
||||
print("Looking up address: {0:#x}".format(LOOKUP_ADDR))
|
||||
lookupsym = sh[LOOKUP_ADDR]
|
||||
print("Symbol resolved !")
|
||||
print(" * __repr__: {0!r}".format(lookupsym))
|
||||
print(" * __str__: {0}".format(lookupsym))
|
||||
print(" * start: {0:#x}".format(lookupsym.start))
|
||||
print(" * addr: {0:#x}".format(lookupsym.addr))
|
||||
print(" * displacement: {0:#x}".format(lookupsym.displacement))
|
||||
print(" * name: {0}".format(lookupsym.name))
|
||||
print(" * fullname: {0}".format(lookupsym.fullname))
|
||||
print(" * module: {0}".format(lookupsym.module))
|
||||
@@ -771,6 +771,7 @@ class Debugger(object):
|
||||
self.breakpoints[self.current_process.pid] = {}
|
||||
self._memory_save[self.current_process.pid] = {}
|
||||
self._module_by_process[self.current_process.pid] = {}
|
||||
self._internal_on_create_process(create_process) # Allow hook for symbol-debugger
|
||||
self._update_debugger_state(debug_event)
|
||||
self._add_exe_to_module_list(create_process)
|
||||
self._setup_pending_breakpoints_new_process(self.current_process)
|
||||
@@ -836,6 +837,9 @@ class Debugger(object):
|
||||
del self._breakpoint_to_reput[self.current_thread.tid]
|
||||
return retvalue
|
||||
|
||||
def _internal_on_create_process(self, create_process):
|
||||
return None
|
||||
|
||||
def _internal_on_load_dll(self, load_dll):
|
||||
return None
|
||||
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import windows
|
||||
import windows.generated_def as gdef
|
||||
from windows.pycompat import int_types
|
||||
|
||||
from . import Debugger
|
||||
from . import symbols
|
||||
|
||||
class SymbolDebugger(Debugger):
|
||||
"""A debugger using the symbol API (hence PDB) for name resolution.
|
||||
To use PDB, a correct version of dbghelp should be configured as well as ``_NT_SYMBOL_PATH``.
|
||||
(See :ref:`debug_symbols_module`)
|
||||
|
||||
This debugger add a ``current_resolver`` variable (A :class:`~windows.debug.symbols.ProcessSymbolHandler`) for the ``current_process``.
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(SymbolDebugger, self).__init__(*args, **kwargs)
|
||||
self._resolvers = {}
|
||||
|
||||
def _internal_on_load_dll(self, load_dll):
|
||||
path = self._get_loaded_dll(load_dll)
|
||||
# Path is used instead of name for naming the module (and can be set to whatever if using file handle)
|
||||
x = self.current_resolver.load_module(load_dll.hFile, path=path, addr=load_dll.lpBaseOfDll)
|
||||
|
||||
def _internal_on_create_process(self, create_process):
|
||||
# Create and setup a symbol resolver for the new process
|
||||
resolver = symbols.ProcessSymbolHandler(self.current_process)
|
||||
self._resolvers[self.current_process.pid] = resolver
|
||||
self.current_resolver = resolver
|
||||
|
||||
def _update_debugger_state(self, debug_event):
|
||||
super(SymbolDebugger, self)._update_debugger_state(debug_event)
|
||||
self.current_resolver = self._resolvers[debug_event.dwProcessId]
|
||||
|
||||
def _resolve(self, addr, target):
|
||||
if isinstance(addr, int_types):
|
||||
return addr
|
||||
if "+" in addr:
|
||||
symbol, deplacement = addr.split("+", 1)
|
||||
deplacement = int(deplacement, 0)
|
||||
else:
|
||||
symbol = addr
|
||||
deplacement = 0
|
||||
try:
|
||||
return self.current_resolver[symbol].addr + deplacement
|
||||
except WindowsError as e:
|
||||
if not e.winerror in (gdef.ERROR_NOT_FOUND, gdef.ERROR_MOD_NOT_FOUND):
|
||||
raise
|
||||
return None
|
||||
+58
-25
@@ -41,15 +41,18 @@ except KeyError as e:
|
||||
|
||||
class SymbolInfoBase(object):
|
||||
"""Represent a Symbol.
|
||||
This class in based on the class `SYMBOL_INFO<https://docs.microsoft.com/en-us/windows/win32/api/dbghelp/ns-dbghelp-symbol_info>`_
|
||||
with the handling on displacement embeded into it."""
|
||||
This class in based on the class `SYMBOL_INFO <https://docs.microsoft.com/en-us/windows/win32/api/dbghelp/ns-dbghelp-symbol_info>`_
|
||||
with the handling on displacement embeded into it.
|
||||
"""
|
||||
# Init on ctypes struct is not always called
|
||||
# resolver & displacement should be set manually
|
||||
CHAR_TYPE = None
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.resolver = kwargs.get("resolver", None)
|
||||
self.displacement = kwargs.get("displacement", 0)
|
||||
#: POUET POUET
|
||||
self.displacement = kwargs.get("displacement", 0) #: POUET POUET
|
||||
|
||||
|
||||
def as_type(self):
|
||||
# assert self.Address == 0 ?
|
||||
@@ -89,6 +92,14 @@ class SymbolInfoBase(object):
|
||||
"""
|
||||
return self.resolver.get_module(self.ModBase)
|
||||
|
||||
@property
|
||||
def tag(self):
|
||||
"""The Tag of the module
|
||||
|
||||
:type: :class:`~windows.generated_def.winstructs.SymTagEnum`
|
||||
"""
|
||||
return gdef.SymTagEnum.mapper[self.Tag]
|
||||
|
||||
def __int__(self):
|
||||
"""An alias for ``addr``"""
|
||||
return self.addr
|
||||
@@ -101,20 +112,35 @@ class SymbolInfoBase(object):
|
||||
|
||||
def __repr__(self):
|
||||
if self.displacement:
|
||||
return '<{0} name="{1}" start={2:#x} displacement={3:#x} tag={4}>'.format(type(self).__name__, self.name, self.start, self.displacement, self.tag)
|
||||
return '<{0} name="{1}" start={2:#x} tag={3}>'.format(type(self).__name__, self.name, self.start, self.tag)
|
||||
return '<{0} name="{1}" start={2:#x} displacement={3:#x} tag={4}>'.format(type(self).__name__, self.name, self.start, self.displacement, self.tag.name)
|
||||
return '<{0} name="{1}" start={2:#x} tag={3}>'.format(type(self).__name__, self.name, self.start, self.tag.name)
|
||||
|
||||
|
||||
class SymbolInfoA(gdef.SYMBOL_INFO, SymbolInfoBase):
|
||||
"""Represent a Symbol.
|
||||
This class in based on the class `SYMBOL_INFO <https://docs.microsoft.com/en-us/windows/win32/api/dbghelp/ns-dbghelp-symbol_info>`_
|
||||
with the handling on displacement embeded into it."""
|
||||
with the handling on displacement embeded into it.s
|
||||
|
||||
Exemple:
|
||||
|
||||
>>> sh = windows.debug.symbols.VirtualSymbolHandler()
|
||||
>>> mod = sh.load_file(r"c:\windows\system32\kernelbase.dll")
|
||||
>>> sym1 = sh["kernelbase!CreateFileW"]
|
||||
>>> sym2 = sh[int(sym1) + 3]
|
||||
>>> sym2
|
||||
<SymbolInfoA name="CreateFileW" start=0x100f20b0 displacement=0x3 tag=SymTagPublicSymbol>
|
||||
>>> hex(sym2.start)
|
||||
'0x100f20b0L'
|
||||
>>> hex(sym2.addr)
|
||||
'0x100f20b3L'
|
||||
>>> hex(sym2.displacement)
|
||||
'0x3L'
|
||||
>>> str(sym2)
|
||||
'kernelbase!CreateFileW+0x3'
|
||||
"""
|
||||
CHAR_TYPE = gdef.CHAR
|
||||
|
||||
class SymbolInfoW(gdef.SYMBOL_INFOW, SymbolInfoBase):
|
||||
"""Represent a Symbol.
|
||||
This class in based on the class `SYMBOL_INFO <https://docs.microsoft.com/en-us/windows/win32/api/dbghelp/ns-dbghelp-symbol_infow>`_
|
||||
with the handling on displacement embeded into it."""
|
||||
CHAR_TYPE = gdef.WCHAR
|
||||
|
||||
# We use the A Api in our code (for now)
|
||||
@@ -407,9 +433,9 @@ class SymbolHandler(object):
|
||||
>>> mod
|
||||
<SymbolModule name="kernelbase" type=SymPdb pdb="wkernelbase.pdb" addr=0x10000000>
|
||||
>>> sh.resolve("kernelbase!CreateFileInternal")
|
||||
<SymbolInfoA name="CreateFileInternal" addr=0x100f2120 tag=5>
|
||||
<SymbolInfoA name="CreateFileInternal" addr=0x100f2120 tag=SymTagFunction>
|
||||
>>> sh[0x100f2042]
|
||||
<SymbolInfoA name="ReadFile" addr=0x100f1ee0 displacement=0x162 tag=5>
|
||||
<SymbolInfoA name="ReadFile" addr=0x100f1ee0 displacement=0x162 tag=SymTagFunction>
|
||||
>>> str(sh[0x100f2042])
|
||||
'kernelbase!ReadFile+0x162'
|
||||
"""
|
||||
@@ -445,9 +471,9 @@ class SymbolHandler(object):
|
||||
>>> sh = windows.debug.symbols.VirtualSymbolHandler()
|
||||
>>> mod = sh.load_file(r"c:\windows\system32\kernelbase.dll")
|
||||
>>> sh.search("kernelbase!CreateFile*")
|
||||
[<SymbolInfoA name="CreateFileInternal" addr=0x100f2120 tag=5>,
|
||||
<SymbolInfoA name="CreateFileMoniker" addr=0x10117d80 tag=5>,
|
||||
<SymbolInfoA name="CreateFile2" addr=0x1011e690 tag=5>,
|
||||
[<SymbolInfoA name="CreateFileInternal" addr=0x100f2120 tag=SymTagFunction>,
|
||||
<SymbolInfoA name="CreateFileMoniker" addr=0x10117d80 tag=SymTagFunction>,
|
||||
<SymbolInfoA name="CreateFile2" addr=0x1011e690 tag=SymTagFunction>,
|
||||
...]
|
||||
"""
|
||||
res = []
|
||||
@@ -455,7 +481,10 @@ class SymbolHandler(object):
|
||||
callback = self.simple_aggregator
|
||||
else:
|
||||
callback = ctypes.WINFUNCTYPE(gdef.BOOL, ctypes.POINTER(SymbolInfo), gdef.ULONG , ctypes.py_object)(callback)
|
||||
windows.winproxy.SymSearch(self.handle, gdef.DWORD64(mod), 0, tag, mask, 0, callback, res, options)
|
||||
|
||||
addr = getattr(mod, "addr", mod) # Retrieve mod.addr, else us the value directly
|
||||
|
||||
windows.winproxy.SymSearch(self.handle, gdef.DWORD64(addr), 0, tag, mask, 0, callback, res, options)
|
||||
for sym in res:
|
||||
sym.resolver = self
|
||||
sym.displacement = 0
|
||||
@@ -490,6 +519,7 @@ class SymbolHandler(object):
|
||||
return SymbolType.from_symbol_info(buff[0], resolver=self)
|
||||
|
||||
|
||||
# TODO: mets de l'huile pour w4kfu
|
||||
class StackWalker(object):
|
||||
def __init__(self, resolver, process=None, thread=None, context=None):
|
||||
self.resolver = resolver
|
||||
@@ -607,15 +637,14 @@ class ProcessSymbolHandler(SymbolHandler):
|
||||
|
||||
Exemple:
|
||||
|
||||
>>> x = windows.debug.symbols.ProcessSymbolHandler(windows.test.pop_proc_64())
|
||||
>>> sh = windows.debug.symbols.ProcessSymbolHandler(windows.test.pop_proc_64())
|
||||
<windows.debug.symbols.ProcessSymbolHandler object at 0x033A2C30>
|
||||
>>> x
|
||||
>>> sh
|
||||
<windows.debug.symbols.ProcessSymbolHandler object at 0x033A2C30>
|
||||
>>> x.load("kernelbase.dll")
|
||||
>>> sh.load("kernelbase.dll")
|
||||
<SymbolModule name="kernelbase" type=SymDeferred pdb="" addr=0x7ffb5b090000>
|
||||
>>> x["kernelbase!CreateProcessA"]
|
||||
<SymbolInfoA name="CreateProcessA" start=0x7ffb5b2371f0 tag=10>
|
||||
|
||||
>>> sh["kernelbase!CreateProcessA"]
|
||||
<SymbolInfoA name="CreateProcessA" start=0x7ffb5b2371f0 tag=SymTagPublicSymbol>
|
||||
"""
|
||||
mods = [x for x in self.target.peb.modules if x.name == name]
|
||||
if not mods:
|
||||
@@ -635,12 +664,12 @@ class ProcessSymbolHandler(SymbolHandler):
|
||||
|
||||
Exemple:
|
||||
|
||||
>>> x = windows.debug.symbols.ProcessSymbolHandler(windows.test.pop_proc_64())
|
||||
>>> x.modules
|
||||
>>> sh = windows.debug.symbols.ProcessSymbolHandler(windows.test.pop_proc_64())
|
||||
>>> sh.modules
|
||||
[]
|
||||
>>> x.refresh()
|
||||
>>> sh.refresh()
|
||||
44
|
||||
>>> x.modules
|
||||
>>> sh.modules
|
||||
[<SymbolModule name="notepad" type=SymDeferred pdb="" addr=0x7ff772b80000>,
|
||||
<SymbolModule name="ntdll" type=SymDeferred pdb="" addr=0x7ffb5d860000>,
|
||||
<SymbolModule name="KERNEL32" type=SymDeferred pdb="" addr=0x7ffb5bb90000>,
|
||||
@@ -683,6 +712,10 @@ class SymbolEngine(object):
|
||||
options = property(get_options, set_options)
|
||||
"""The options of the Symbol engine
|
||||
(`see options <https://docs.microsoft.com/en-us/windows/win32/api/dbghelp/nf-dbghelp-symsetoptions#parameters>`_)
|
||||
|
||||
.. note::
|
||||
|
||||
Default options are: ``gdef.SYMOPT_DEFERRED_LOADS + gdef.SYMOPT_UNDNAME``
|
||||
"""
|
||||
|
||||
engine = SymbolEngine()
|
||||
|
||||
@@ -15,29 +15,53 @@ def GetFileVersionInfoA(lptstrFilename, dwHandle=0, dwLen=None, lpData=NeededPar
|
||||
dwLen = len(lpData)
|
||||
return GetFileVersionInfoA.ctypes_function(lptstrFilename, dwHandle, dwLen, lpData)
|
||||
|
||||
|
||||
@VersionProxy()
|
||||
def GetFileVersionInfoW(lptstrFilename, dwHandle=0, dwLen=None, lpData=NeededParameter):
|
||||
if dwLen is None and lpData is not None:
|
||||
dwLen = len(lpData)
|
||||
return GetFileVersionInfoW.ctypes_function(lptstrFilename, dwHandle, dwLen, lpData)
|
||||
|
||||
|
||||
@VersionProxy()
|
||||
def GetFileVersionInfoExA(dwFlags, lpwstrFilename, dwHandle, dwLen, lpData):
|
||||
return GetFileVersionInfoExA.ctypes_function(dwFlags, lpwstrFilename, dwHandle, dwLen, lpData)
|
||||
|
||||
|
||||
@VersionProxy()
|
||||
def GetFileVersionInfoExW(dwFlags, lpwstrFilename, dwHandle, dwLen, lpData):
|
||||
return GetFileVersionInfoExW.ctypes_function(dwFlags, lpwstrFilename, dwHandle, dwLen, lpData)
|
||||
|
||||
|
||||
@VersionProxy()
|
||||
def GetFileVersionInfoSizeA(lptstrFilename, lpdwHandle=None):
|
||||
if lpdwHandle is None:
|
||||
lpdwHandle = ctypes.byref(gdef.DWORD())
|
||||
return GetFileVersionInfoSizeA.ctypes_function(lptstrFilename, lpdwHandle)
|
||||
|
||||
|
||||
@VersionProxy()
|
||||
def GetFileVersionInfoSizeW(lptstrFilename, lpdwHandle=None):
|
||||
if lpdwHandle is None:
|
||||
lpdwHandle = ctypes.byref(gdef.DWORD())
|
||||
return GetFileVersionInfoSizeW.ctypes_function(lptstrFilename, lpdwHandle)
|
||||
|
||||
|
||||
@VersionProxy()
|
||||
def GetFileVersionInfoSizeExA(dwFlags, lpwstrFilename, lpdwHandle=None):
|
||||
return GetFileVersionInfoSizeExA.ctypes_function(dwFlags, lpwstrFilename, lpdwHandle)
|
||||
|
||||
|
||||
@VersionProxy()
|
||||
def GetFileVersionInfoSizeExW(dwFlags, lpwstrFilename, lpdwHandle=None):
|
||||
return GetFileVersionInfoSizeExW.ctypes_function(dwFlags, lpwstrFilename, lpdwHandle)
|
||||
|
||||
|
||||
@VersionProxy()
|
||||
def VerQueryValueA(pBlock, lpSubBlock, lplpBuffer, puLen):
|
||||
return VerQueryValueA.ctypes_function(pBlock, lpSubBlock, lplpBuffer, puLen)
|
||||
|
||||
|
||||
@VersionProxy()
|
||||
def VerQueryValueW(pBlock, lpSubBlock, lplpBuffer, puLen):
|
||||
return VerQueryValueW.ctypes_function(pBlock, lpSubBlock, lplpBuffer, puLen)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user