diff --git a/image_creator/os_type/windows/__init__.py b/image_creator/os_type/windows/__init__.py
index 91a340a54c845926ece6f39c8aa2dbafc3af2ae3..35c313e8576fad5eb35a947c573e8c8f4ad26a2e 100644
--- a/image_creator/os_type/windows/__init__.py
+++ b/image_creator/os_type/windows/__init__.py
@@ -466,6 +466,7 @@ class Windows(OSBase):
self.out.output("Preparing media for boot ...", False)
with self.mount(readonly=False, silent=True):
+ activated = self.registry.reset_account(admin)
v_val = self.registry.reset_passwd(admin)
disabled_uac = self.registry.update_uac_remote_setting(1)
self._add_boot_scripts()
@@ -533,9 +534,11 @@ class Windows(OSBase):
if disabled_uac:
self.registry.update_uac_remote_setting(0)
+ if not activated:
+ self.registry.reset_account(admin, False)
+
if not self.sysprepped:
# Reset the old password
- admin = self.sysprep_params['admin'].value
self.registry.reset_passwd(admin, v_val)
self.registry.update_firewalls(*firewall_states)
@@ -786,6 +789,7 @@ class Windows(OSBase):
with self.mount(readonly=False, silent=True):
admin = self.sysprep_params['admin'].value
v_val = self.registry.reset_passwd(admin)
+ activated = self.registry.reset_account(admin)
self.registry.enable_autologon(admin)
tmp = uuid.uuid4().hex
diff --git a/image_creator/os_type/windows/registry.py b/image_creator/os_type/windows/registry.py
index 7715bc9224c73f90509941a82a2ef062b7244603..ff6ba3fc6107f30f9d2d079bfdac5d6ccbb42e31 100644
--- a/image_creator/os_type/windows/registry.py
+++ b/image_creator/os_type/windows/registry.py
@@ -330,7 +330,7 @@ class Registry(object):
# http://www.beginningtoseethelight.org/ntsecurity/index.htm
# #D3BC3F5643A17823
fmt = '%ds4x8s4x%ds' % (0xa0, len(v_val) - 0xb0)
- new = ("\x00" * 4).join(struct.unpack(fmt, v_val))
+ new = ("\x00" * 4).join(struct.unpack(fmt, v_val))
hive.node_set_value(rid_node, REG_BINARY('V', new))
hive.commit(None)
@@ -341,6 +341,47 @@ class Registry(object):
assert 'old' in parent, "user: `%s' does not exist" % user
return parent['old']
+ def reset_account(self, user, activate=True):
+
+ # This is a hack. I cannot assign a new value to nonlocal variable.
+ # This is why I'm using a dict
+ state = {}
+
+ # Convert byte to int
+ to_int = lambda b: int(b.encode('hex'), 16)
+
+ # Under HKEY_LOCAL_MACHINE\SAM\SAM\Domains\Account\Users\%RID% there is
+ # an F field that contains information about this user account. Bytes
+ # 56 & 57 are the account type and status flags. The first bit is the
+ # 'account disabled' bit:
+ #
+ # http://www.beginningtoseethelight.org/ntsecurity/index.htm
+ # #8603CF0AFBB170DD
+ #
+ isactive = lambda f: (to_int(f[56]) & 0x01) == 0
+
+ def update_f_field(hive, username, rid_node):
+
+ field = hive.node_get_value(rid_node, 'F')
+ f_type, f_val = hive.value_value(field)
+ assert f_type == 3L, "F field type (=%d) isn't REG_BINARY" % f_type
+
+ state['old'] = isactive(f_val)
+ if activate is state['old']:
+ # nothing to do
+ return
+
+ mask = (lambda b: b & 0xfe) if activate else (lambda b: b | 0x01)
+ new = struct.pack("56sB23s", f_val[:56], mask(to_int(f_val[56])),
+ f_val[57:])
+
+ hive.node_set_value(rid_node, REG_BINARY('F', new))
+ hive.commit(None)
+
+ self._foreach_user([user], update_f_field, write=True)
+
+ return state['old']
+
def _foreach_user(self, userlist, action, write=False):
"""Performs an action on the RID node of a user in the registry, for
every user found in the userlist. If userlist is empty, it performs the