mirror of
https://github.com/reactos/reactos.git
synced 2024-12-31 19:42:51 +00:00
0e14378d3e
This DLL was exporting legacy NT-incompatible or ROS-specific SM client functions, that have been since 10 years now (2012) replaced by the new NT-compatible SM: - SmConnectApiPort(): was just SmConnectToSm(). - SmCompleteSession(): The legacy SMSS used it for when a subsystem initialization was finished. Now (NT-compatible) this function is called by subsystems **only** when a subsystem session **terminates**: SmSessionComplete(). - SmExecuteProgram(): was just the client side of SmLoadDeferedSubSystem() (whose server side is not implemented yet). The legacy SM "old" SmExecPgm implementation actually was "SmLoadDeferedSubSystem"... - SmLookupSubsystem(): is a utility-only function to read any registry value inside "Session Manager\SubSystems". Move SMDLL's readme into SMLIB and update its contents. Collect some residual useful functions into smutils.c (and moved in SMLIB, though not compiled yet): - SmExecuteProgram(), now implemented as a wrapper around SmExecPgm(); - SmLookupSubsystem(), described above; - SmQueryInformation(), that retrieves a list of currently-running subsystems. [SMLIB] Validate SbApiPortName's length in SmConnectToSm(). Fix CommandLine length validation in SmStartCsr(). Add documentation (+ SAL annotations) to the NT-compatible SMSS client functions. smmsg.h: Add both Win32 and Win64 struct sizes C_ASSERTs for those whose size change between these two processor architecture sizes. [SMLIB] Introduce SmSendMsgToSm() as helper to send data into the SM LPC port. + Make the other API functions use it. It should be observed that in Vista+, both functions SmConnectToSm() and this new SmSendMsgToSm() are exported by NTDLL under the names RtlConnectToSm() and RtlSendMsgToSm() (and use the same signature). See: https://www.geoffchappell.com/studies/windows/win32/ntdll/history/names60.htm [NTDLL] Correctly stub RtlConnectToSm() and RtlSendMsgToSm(). [NTDLL_VISTA] Link to SMLIB and simply export RtlConnectToSm() and RtlSendMsgToSm().
391 lines
10 KiB
Python
391 lines
10 KiB
Python
'''
|
|
PROJECT: ReactOS baseaddress updater
|
|
LICENSE: MIT (https://spdx.org/licenses/MIT)
|
|
PURPOSE: Update baseaddresses of all modules
|
|
COPYRIGHT: Copyright 2017,2018 Mark Jansen (mark.jansen@reactos.org)
|
|
'''
|
|
|
|
from __future__ import print_function, absolute_import, division
|
|
|
|
USAGE = """
|
|
This script will update the baseaddresses of all modules, based on the build output.
|
|
|
|
Specify the build output dir as commandline argument to the script:
|
|
`python gen_baseaddress.py C:\\Users\\Mark\\reactos\\output-MinGW-i386`
|
|
|
|
Multiple directories can be specified:
|
|
`python gen_baseaddress r:/build/msvc r:/build/gcc`
|
|
"""
|
|
|
|
import os
|
|
import struct
|
|
import sys
|
|
|
|
try:
|
|
import pefile
|
|
except ImportError:
|
|
print('# Please install pefile from pip or https://github.com/erocarrera/pefile')
|
|
sys.exit(-1)
|
|
|
|
|
|
ALL_EXTENSIONS = (
|
|
'.dll', '.acm', '.ax', '.cpl', '.drv', '.ocx'
|
|
)
|
|
|
|
PRIORITIES = (
|
|
'ntdll.dll',
|
|
'kernel32.dll',
|
|
'msvcrt.dll',
|
|
'advapi32.dll',
|
|
'gdi32.dll',
|
|
'user32.dll',
|
|
'dhcpcsvc.dll',
|
|
'dnsapi.dll',
|
|
'icmp.dll',
|
|
'iphlpapi.dll',
|
|
'ws2_32.dll',
|
|
'ws2help.dll',
|
|
'shlwapi.dll',
|
|
'rpcrt4.dll',
|
|
'comctl32.dll',
|
|
'ole32.dll',
|
|
'winspool.drv',
|
|
'winmm.dll',
|
|
'comdlg32.dll',
|
|
'shell32.dll',
|
|
'lz32.dll',
|
|
'version.dll',
|
|
'oleaut32.dll',
|
|
'setupapi.dll',
|
|
'mpr.dll',
|
|
'crypt32.dll',
|
|
'wininet.dll',
|
|
'urlmon.dll',
|
|
'psapi.dll',
|
|
'imm32.dll',
|
|
'msvfw32.dll',
|
|
'dbghelp.dll',
|
|
'devmgr.dll',
|
|
'msacm32.dll',
|
|
'netapi32.dll',
|
|
'powrprof.dll',
|
|
'secur32.dll',
|
|
'wintrust.dll',
|
|
'avicap32.dll',
|
|
'cabinet.dll',
|
|
'dsound.dll',
|
|
'glu32.dll',
|
|
'opengl32.dll',
|
|
'riched20.dll',
|
|
'userenv.dll',
|
|
'uxtheme.dll',
|
|
'cryptui.dll',
|
|
'csrsrv.dll',
|
|
'basesrv.dll',
|
|
'winsrv.dll',
|
|
'dplayx.dll',
|
|
'gdiplus.dll',
|
|
'msimg32.dll',
|
|
'mswsock.dll',
|
|
'oledlg.dll',
|
|
'rasapi32.dll',
|
|
'rsaenh.dll',
|
|
'samlib.dll',
|
|
'sensapi.dll',
|
|
'sfc_os.dll',
|
|
'snmpapi.dll',
|
|
'spoolss.dll',
|
|
'usp10.dll',
|
|
)
|
|
|
|
EXCLUDE = (
|
|
'bmfd.dll',
|
|
'bootvid.dll',
|
|
'framebuf.dll',
|
|
'framebuf_new.dll',
|
|
'ftfd.dll',
|
|
'fusion.dll',
|
|
'genincdata.dll',
|
|
'hal.dll',
|
|
'halaacpi.dll',
|
|
'halacpi.dll',
|
|
'halapic.dll',
|
|
'kbda1.dll',
|
|
'kbda2.dll',
|
|
'kbda3.dll',
|
|
'kbdal.dll',
|
|
'kbdarme.dll',
|
|
'kbdarmw.dll',
|
|
'kbdaze.dll',
|
|
'kbdazel.dll',
|
|
'kbdbe.dll',
|
|
'kbdbga.dll',
|
|
'kbdbgt.dll',
|
|
'kbdblr.dll',
|
|
'kbdbr.dll',
|
|
'kbdbu.dll',
|
|
'kbdbur.dll',
|
|
'kbdcan.dll',
|
|
'kbdcr.dll',
|
|
'kbdcz.dll',
|
|
'kbdcz1.dll',
|
|
'kbdda.dll',
|
|
'kbddv.dll',
|
|
'kbdest.dll',
|
|
'kbdfc.dll',
|
|
'kbdfi.dll',
|
|
'kbdfr.dll',
|
|
'kbdgeo.dll',
|
|
'kbdgerg.dll',
|
|
'kbdgneo.dll',
|
|
'kbdgr.dll',
|
|
'kbdgr1.dll',
|
|
'kbdhe.dll',
|
|
'kbdheb.dll',
|
|
'kbdhu.dll',
|
|
'kbdic.dll',
|
|
'kbdinasa.dll',
|
|
'kbdinben.dll',
|
|
'kbdindev.dll',
|
|
'kbdinguj.dll',
|
|
'kbdinmal.dll',
|
|
'kbdir.dll',
|
|
'kbdit.dll',
|
|
'kbdjpn.dll',
|
|
'kbdkaz.dll',
|
|
'kbdkor.dll',
|
|
'kbdla.dll',
|
|
'kbdlt1.dll',
|
|
'kbdlv.dll',
|
|
'kbdmac.dll',
|
|
'kbdne.dll',
|
|
'kbdno.dll',
|
|
'kbdpl.dll',
|
|
'kbdpl1.dll',
|
|
'kbdpo.dll',
|
|
'kbdro.dll',
|
|
'kbdru.dll',
|
|
'kbdru1.dll',
|
|
'kbdsg.dll',
|
|
'kbdsl.dll',
|
|
'kbdsl1.dll',
|
|
'kbdsp.dll',
|
|
'kbdsw.dll',
|
|
'kbdtat.dll',
|
|
'kbdth0.dll',
|
|
'kbdth1.dll',
|
|
'kbdth2.dll',
|
|
'kbdth3.dll',
|
|
'kbdtuf.dll',
|
|
'kbdtuq.dll',
|
|
'kbduk.dll',
|
|
'kbdur.dll',
|
|
'kbdurs.dll',
|
|
'kbdus.dll',
|
|
'kbdusa.dll',
|
|
'kbdusl.dll',
|
|
'kbdusr.dll',
|
|
'kbdusx.dll',
|
|
'kbduzb.dll',
|
|
'kbdvntc.dll',
|
|
'kbdycc.dll',
|
|
'kbdycl.dll',
|
|
'kdcom.dll',
|
|
'kdvbox.dll',
|
|
'vgaddi.dll',
|
|
'dllexport_test_dll1.dll',
|
|
'dllexport_test_dll2.dll',
|
|
'dllimport_test.dll',
|
|
'MyEventProvider.dll',
|
|
'w32kdll_2k3sp2.dll',
|
|
'w32kdll_ros.dll',
|
|
'w32kdll_xpsp2.dll',
|
|
)
|
|
|
|
IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b
|
|
IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b
|
|
|
|
IMAGE_TYPES = {
|
|
IMAGE_NT_OPTIONAL_HDR32_MAGIC: 0,
|
|
IMAGE_NT_OPTIONAL_HDR64_MAGIC: 0
|
|
}
|
|
|
|
def is_x64():
|
|
return IMAGE_TYPES[IMAGE_NT_OPTIONAL_HDR64_MAGIC] > IMAGE_TYPES[IMAGE_NT_OPTIONAL_HDR32_MAGIC]
|
|
|
|
def size_of_image(filename):
|
|
with open(filename, 'rb') as fin:
|
|
if fin.read(2) != b'MZ':
|
|
print(filename, 'No dos header found!')
|
|
return 0
|
|
fin.seek(0x3C)
|
|
e_lfanew = struct.unpack('i', fin.read(4))[0]
|
|
fin.seek(e_lfanew)
|
|
if fin.read(4) != b'PE\0\0':
|
|
print(filename, 'No PE header found!')
|
|
return 0
|
|
fin.seek(e_lfanew + 0x18)
|
|
pe_magic = struct.unpack('h', fin.read(2))[0]
|
|
if pe_magic in IMAGE_TYPES.keys():
|
|
IMAGE_TYPES[pe_magic] += 1
|
|
fin.seek(e_lfanew + 0x50)
|
|
pe_size_of_image = struct.unpack('i', fin.read(4))[0]
|
|
return pe_size_of_image
|
|
print(filename, 'Unknown executable format!')
|
|
return 0
|
|
|
|
|
|
class Module(object):
|
|
def __init__(self, name, address, size, filename):
|
|
self._name = name
|
|
self.address = address
|
|
self.size = size
|
|
self._reserved = address != 0
|
|
self.filename = filename
|
|
|
|
def gen_baseaddress(self, output_file):
|
|
name, ext = os.path.splitext(self._name)
|
|
postfix = ''
|
|
if ext in('.acm', '.drv') and self._name != 'winspool.drv':
|
|
name = self._name
|
|
if name == 'ntdll':
|
|
postfix = ' # should be above 0x%08x' % self.address
|
|
elif self._reserved:
|
|
postfix = ' # reserved'
|
|
output_file.write('set(baseaddress_%-30s 0x%08x)%s\n' % (name, self.address, postfix))
|
|
|
|
def end(self):
|
|
return self.address + self.size
|
|
|
|
def __repr__(self):
|
|
return '%s (0x%08x - 0x%08x)' % (self._name, self.address, self.end())
|
|
|
|
class MemoryLayout(object):
|
|
def __init__(self, startaddress):
|
|
self.addresses = []
|
|
self.found = {}
|
|
self.reserved = {}
|
|
self.initial = startaddress
|
|
self.start_at = 0
|
|
self.module_padding = 0x2000
|
|
|
|
def add_reserved(self, name, address):
|
|
self.reserved[name] = (address, 0)
|
|
|
|
def add(self, filename, name):
|
|
size = size_of_image(filename)
|
|
addr = 0
|
|
if name in self.found:
|
|
return # Assume duplicate files (rshell, ...) are 1:1 copies
|
|
if name in self.reserved:
|
|
addr = self.reserved[name][0]
|
|
self.reserved[name] = (addr, size)
|
|
self.found[name] = Module(name, addr, size, filename)
|
|
|
|
def _next_address(self, size):
|
|
if self.start_at:
|
|
addr = (self.start_at - size - self.module_padding - 0xffff) & 0xffff0000
|
|
self.start_at = addr
|
|
else:
|
|
addr = self.start_at = self.initial
|
|
return addr
|
|
|
|
def next_address(self, size):
|
|
while True:
|
|
current_start = self._next_address(size)
|
|
current_end = current_start + size + self.module_padding
|
|
# Is there overlap with reserved modules?
|
|
for key, reserved in self.reserved.items():
|
|
res_start = reserved[0]
|
|
res_end = res_start + reserved[1] + self.module_padding
|
|
if (res_start <= current_start <= res_end) or \
|
|
(res_start <= current_end <= res_end) or \
|
|
(current_start < res_start and current_end > res_end):
|
|
# We passed this reserved item, we can remove it now
|
|
self.start_at = min(res_start, current_start)
|
|
del self.reserved[key]
|
|
current_start = 0
|
|
break
|
|
# No overlap with a reserved module?
|
|
if current_start:
|
|
return current_start
|
|
|
|
def update(self, priorities):
|
|
# sort addresses, should only contain reserved modules at this point!
|
|
for key, reserved in self.reserved.items():
|
|
assert reserved[1] != 0, key
|
|
for curr in priorities:
|
|
if not curr in self.found:
|
|
print('# Did not find', curr, '!')
|
|
else:
|
|
obj = self.found[curr]
|
|
del self.found[curr]
|
|
if not obj.address:
|
|
obj.address = self.next_address(obj.size)
|
|
self.addresses.append(obj)
|
|
# We handled all known modules now, run over the rest we found
|
|
for key in sorted(self.found):
|
|
obj = self.found[key]
|
|
obj.address = self.next_address(obj.size)
|
|
self.addresses.append(obj)
|
|
|
|
def gen_baseaddress(self, output_file):
|
|
for obj in self.addresses:
|
|
obj.gen_baseaddress(output_file)
|
|
|
|
def get_target_file(ntdll_path):
|
|
if 'pefile' in globals():
|
|
ntdll_pe = pefile.PE(ntdll_path, fast_load=True)
|
|
names = [sect.Name.strip(b'\0') for sect in ntdll_pe.sections]
|
|
count = b'|'.join(names).count(b'/')
|
|
if b'.rossym' in names:
|
|
return 'baseaddress.cmake'
|
|
elif is_x64():
|
|
return 'baseaddress_msvc_x64.cmake'
|
|
elif count == 0:
|
|
return 'baseaddress_msvc.cmake'
|
|
elif count > 3:
|
|
return 'baseaddress_dwarf.cmake'
|
|
else:
|
|
assert False, "Unknown"
|
|
return None
|
|
|
|
def run_dir(target):
|
|
layout = MemoryLayout(0x7c920000)
|
|
layout.add_reserved('user32.dll', 0x77a20000)
|
|
IMAGE_TYPES[IMAGE_NT_OPTIONAL_HDR64_MAGIC] = 0
|
|
IMAGE_TYPES[IMAGE_NT_OPTIONAL_HDR32_MAGIC] = 0
|
|
for root, _, files in os.walk(target):
|
|
for dll in [filename for filename in files if filename.endswith(ALL_EXTENSIONS)]:
|
|
if not dll in EXCLUDE and not dll.startswith('api-ms-win-'):
|
|
layout.add(os.path.join(root, dll), dll)
|
|
ntdll_path = layout.found['ntdll.dll'].filename
|
|
target_file = get_target_file(ntdll_path)
|
|
if target_file:
|
|
target_dir = os.path.realpath(os.path.dirname(os.path.dirname(__file__)))
|
|
target_path = os.path.join(target_dir, 'cmake', target_file)
|
|
output_file = open(target_path, "w")
|
|
else:
|
|
output_file = sys.stdout
|
|
with output_file:
|
|
output_file.write('# Generated from {}\n'.format(target))
|
|
output_file.write('# Generated by sdk/tools/gen_baseaddress.py\n\n')
|
|
layout.update(PRIORITIES)
|
|
layout.gen_baseaddress(output_file)
|
|
|
|
def main():
|
|
dirs = sys.argv[1:]
|
|
if len(dirs) < 1:
|
|
trydir = os.getcwd()
|
|
print(USAGE)
|
|
print('No path specified, trying the working directory: ', trydir)
|
|
dirs = [trydir]
|
|
for onedir in dirs:
|
|
if onedir.lower() in ['-help', '/help', '/h', '-h', '/?', '-?']:
|
|
print(USAGE)
|
|
else:
|
|
run_dir(onedir)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|