utils: add set_windows_hostname

Add function to redefine the hostname of a Windows install.
Windows hostnames can't be larger than 15 characters due to
legacy heritage.

Hostname modification is done by modifying 3 registry values in
the ControlSetXXX entry of the SYSTEM hive. ControlSet001 is
generally the entry to be edited but one must query the value
of the 'Current' key in the 'Select' entry of the SYSTEM hive
to retrieve the active ControlSet.

The hostname has to be introduced in the following entries:
path = 'ControlSetXX/Control/ComputerName/ComputerName'
key = 'ComputerName'

path = 'ControlSetXXX/Services/Tcpip/Parameters'
key = 'HostName'
key = 'NV Hostname'

The value to store in those keys is of tipe SZ and has to be
encoded in UCS-2 Little Endian (utf-16-le).
master
Alejandro Sirgo Rica 2024-07-25 16:34:35 +02:00
parent 567fea276e
commit adbf02d170
1 changed files with 47 additions and 0 deletions

View File

@ -22,6 +22,50 @@ from socket import gethostname
CONFIGUREOS_LEGACY_ENABLED = False
def set_windows_hostname(disk, partition, name):
logging.info(f'Configuring hostname')
if len(name) > 15:
logging.warning(f'Windows does nor permit hostnames that exceed 15 characters. Truncating {name}')
name = name[0:15]
byte_name = name.encode(WINDOWS_HIVE_ENCODING)
device = get_partition_device(disk, partition)
mountpoint = device.replace('dev', 'mnt')
if not mount_mkdir(device, mountpoint):
raise OgError(f'Unable to mount {device} into {mountpoint}')
try:
hive_path = mountpoint + WINDOWS_HIVE_SYSTEM
hive = hive_handler_open(hive_path, write=True)
root = hive.root()
select_node = get_node_child_from_path(hive, root, 'Select')
current_control_set_number = get_value_from_node(hive, select_node, 'Current')
control_set = f'ControlSet{current_control_set_number:03}'
computer_name_node = get_node_child_from_path(hive, root, f'{control_set}/Control/ComputerName/ComputerName')
name_value = {'key': 'ComputerName', 't': RegistryType.SZ.value, 'value': byte_name}
hive.node_set_value(computer_name_node, name_value)
parameters_node = get_node_child_from_path(hive, root, f'{control_set}/Services/Tcpip/Parameters')
hostname_value = {'key': 'HostName', 't': RegistryType.SZ.value, 'value': byte_name}
hive.node_set_value(parameters_node, hostname_value)
nvhostname_value = {'key': 'NV Hostname', 't': RegistryType.SZ.value, 'value': byte_name}
hive.node_set_value(parameters_node, nvhostname_value)
hive.commit(hive_path)
except Exception as e:
raise OgError(f'Unable to configure Windows hostname: {e}') from e
finally:
umount(mountpoint)
def configure_os_custom(disk, partition):
if not shutil.which('configureOsCustom'):
raise OgError('configureOsCustom not found')
@ -115,6 +159,9 @@ def configure_os_linux(disk, partition):
def configure_os_windows(disk, partition):
hostname = gethostname()
set_windows_hostname(disk, partition, hostname)
if is_uefi_supported():
restore_windows_efi_bootloader(disk, partition)