def SetInfo(userName=None): "Attempts to change the current users comment, then set it back" if userName is None: userName = win32api.GetUserName() oldData = win32net.NetUserGetInfo(server, userName, 3) try: d = oldData.copy() d["usr_comment"] = "Test comment" win32net.NetUserSetInfo(server, userName, 3, d) new = win32net.NetUserGetInfo(server, userName, 3)['usr_comment'] if str(new) != "Test comment": raise RuntimeError, "Could not read the same comment back - got %s" % new print "Changed the data for the user" finally: win32net.NetUserSetInfo(server, userName, 3, oldData)
def disablePasswdExpiry(user, servername=SERVERNAME): try: userinfo = win32net.NetUserGetInfo(servername, user, 3) userinfo['flags'] |= win32netcon.UF_DONT_EXPIRE_PASSWD win32net.NetUserSetInfo(servername, user, 3, userinfo) except win32net.error: mesg("\n @@@ Warning: Could not disable password expiry for user %s. @@@\n\n", user)
def setPasswd(user, password, servername=SERVERNAME): try: userinfo = win32net.NetUserGetInfo(servername, user, 2) userinfo['password'] = password win32net.NetUserSetInfo(servername, user, 2, userinfo) except win32net.error: mesg("\n @@@ Warning: Could not set password for user %s. @@@\n\n", user)
def create_local_student_account(user_name, full_name, password): global STUDENTS_GROUP # Ensure the Students group exists ret = create_local_students_group() # Create local student account student = None try: print("\tAdding student account...") accounts.User.create(user_name, password) except pywintypes.error as err: if err[2] == "The account already exists.": pass else: # Unexpected error print(str(err)) ret = False # Get the student object student = accounts.user(user_name) # Set properties for this student # win32net.NetUserChangePassword(None, user_name, old_pw, password) user_data = dict() user_data['name'] = user_name user_data['full_name'] = full_name user_data['password'] = password user_data[ 'flags'] = win32netcon.UF_NORMAL_ACCOUNT | win32netcon.UF_PASSWD_CANT_CHANGE | win32netcon.UF_DONT_EXPIRE_PASSWD | win32netcon.UF_SCRIPT user_data['priv'] = win32netcon.USER_PRIV_USER user_data['comment'] = 'OPE Student Account' # user_data['home_dir'] = home_dir # user_data['home_dir_drive'] = "h:" user_data['primary_group_id'] = ntsecuritycon.DOMAIN_GROUP_RID_USERS user_data['password_expired'] = 0 user_data['acct_expires'] = win32netcon.TIMEQ_FOREVER win32net.NetUserSetInfo(None, user_name, 3, user_data) # Add student to the students group print("\tAdding student to students group...") grp = accounts.LocalGroup(accounts.group(STUDENTS_GROUP).sid) try: grp.add(student) except pywintypes.error as err: if err[2] == "The specified account name is already a member of the group.": pass else: # Unexpected error print(str(err)) ret = False # # home_dir = "%s\\%s" % (server_name, user_name) # return ret
def create_local_admin_account(user_name, full_name, password): # Create local admin account ret = True try: p("}}yn\tAdding Admin account (" + user_name + ")...}}xx") accounts.User.create(user_name, password) # p("}}yn\t\tDone.}}xx") # except pywintypes.error as ex: except Exception as ex: if ex.args[2] == "The account already exists.": pass else: # Unexpected error p("}}rb" + str(ex) + "}}xx") ret = False user_data = dict() user_data['name'] = user_name user_data['full_name'] = full_name #user_data['password'] = UserAccounts.generate_random_password() user_data['flags'] = UserAccounts.ENABLE_ACCOUNT_FLAGS user_data['priv'] = win32netcon.USER_PRIV_ADMIN user_data['comment'] = 'OPE Admin Account' # user_data['home_dir'] = home_dir # user_data['home_dir_drive'] = "h:" user_data['primary_group_id'] = ntsecuritycon.DOMAIN_GROUP_RID_USERS user_data['password_expired'] = 0 user_data['acct_expires'] = win32netcon.TIMEQ_FOREVER win32net.NetUserSetInfo(None, user_name, 3, user_data) # Set password try: user_data['password'] = password win32net.NetUserSetInfo(None, user_name, 3, user_data) except Exception as ex: p("}}rbERROR setting password for " + user_name + "}}xx\n" + str(ex)) if not UserAccounts.set_default_groups_for_admin(user_name): ret = False return ret
def change_password_next_logon(self, username): """Force the given user to change the password at next logon.""" user_info = self._get_user_info(username, 4) user_info["flags"] &= ~win32netcon.UF_DONT_EXPIRE_PASSWD user_info["password_expired"] = 1 try: win32net.NetUserSetInfo(None, username, 4, user_info) except win32net.error as ex: raise exception.CloudbaseInitException( "Setting password expiration failed: %s" % ex.args[2])
def disable_account(name): user_info = get_account_info(name) # disable account user_info['flags'] = user_info.get('flags') | win32netcon.UF_ACCOUNTDISABLE try: win32net.NetUserSetInfo(None, name, 4, user_info) except pywintypes.error as e: print("ERROR: permission denied.") print(e) sys.exit(1) print("OK: account \"{}\" is disabled.".format(name))
def changeUserPassword(user: str, oldPassword: str, newPassword: str) -> None: # lpUser = LPCWSTR(user) # lpOldPassword = LPCWSTR(oldPassword) # lpNewPassword = LPCWSTR(newPassword) # res = ctypes.windll.netapi32.NetUserChangePassword(None, lpUser, lpOldPassword, lpNewPassword) # Try to set new password "a las bravas", ignoring old one. This will not work with domain users res = win32net.NetUserSetInfo(None, user, 1003, {'password': newPassword}) if res: # Log the error, and raise exception to parent error = getErrorMessage(res) raise Exception('Error changing password for user {}: {} {}'.format(user, res, error))
def set_user_password(self, username, password, password_expires=False): user_info = self._get_user_info(username, 1) user_info["password"] = password if password_expires: user_info["flags"] &= ~win32netcon.UF_DONT_EXPIRE_PASSWD else: user_info["flags"] |= win32netcon.UF_DONT_EXPIRE_PASSWD try: win32net.NetUserSetInfo(None, username, 1, user_info) except win32net.error as ex: raise exception.CloudbaseInitException( "Set user password failed: %s" % ex.args[2])
def disable_account(account_name=None): if account_name is None: account_name = util.get_param(2, None) if account_name is None: p("}}enInvalid User name - not disabling account!}}xx") return False try: user_data = dict() user_data['flags'] = UserAccounts.DISABLE_ACCOUNT_FLAGS #win32netcon.UF_SCRIPT | win32netcon.UF_ACCOUNTDISABLE win32net.NetUserSetInfo(None, account_name, 1008, user_data) except Exception as ex: p("}}rnError - Unable to disable account: " + str(account_name) + "}}xx\n" + \ str(ex)) return False return True
def update(name, password=None, fullname=None, description=None, home=None, homedrive=None, logonscript=None, profile=None, expiration_date=None, expired=None, account_disabled=None, unlock_account=None, password_never_expires=None, disallow_change_password=None): r''' Updates settings for the windows user. Name is the only required parameter. Settings will only be changed if the parameter is passed a value. .. versionadded:: 2015.8.0 Args: name (str): The user name to update. password (str, optional): New user password in plain text. fullname (str, optional): The user's full name. description (str, optional): A brief description of the user account. home (str, optional): The path to the user's home directory. homedrive (str, optional): The drive letter to assign to the home directory. Must be the Drive Letter followed by a colon. ie: U: logonscript (str, optional): The path to the logon script. profile (str, optional): The path to the user's profile directory. expiration_date (date, optional): The date and time when the account expires. Can be a valid date/time string. To set to never expire pass the string 'Never'. expired (bool, optional): Pass `True` to expire the account. The user will be prompted to change their password at the next logon. Pass `False` to mark the account as 'not expired'. You can't use this to negate the expiration if the expiration was caused by the account expiring. You'll have to change the `expiration_date` as well. account_disabled (bool, optional): True disables the account. False enables the account. unlock_account (bool, optional): True unlocks a locked user account. False is ignored. password_never_expires (bool, optional): True sets the password to never expire. False allows the password to expire. disallow_change_password (bool, optional): True blocks the user from changing the password. False allows the user to change the password. Returns: bool: True if successful. False is unsuccessful. CLI Example: .. code-block:: bash salt '*' user.update bob password=secret profile=C:\Users\Bob home=\\server\homeshare\bob homedrive=U: ''' if six.PY2: name = _to_unicode(name) password = _to_unicode(password) fullname = _to_unicode(fullname) description = _to_unicode(description) home = _to_unicode(home) homedrive = _to_unicode(homedrive) logonscript = _to_unicode(logonscript) profile = _to_unicode(profile) # Make sure the user exists # Return an object containing current settings for the user try: user_info = win32net.NetUserGetInfo(None, name, 4) except win32net.error as exc: (number, context, message) = exc log.error('Failed to update user {0}'.format(name)) log.error('nbr: {0}'.format(exc.winerror)) log.error('ctx: {0}'.format(exc.funcname)) log.error('msg: {0}'.format(exc.strerror)) return False # Check parameters to update # Update the user object with new settings if password: user_info['password'] = password if home: user_info['home_dir'] = home if homedrive: user_info['home_dir_drive'] = homedrive if description: user_info['comment'] = description if logonscript: user_info['script_path'] = logonscript if fullname: user_info['full_name'] = fullname if profile: user_info['profile'] = profile if expiration_date: if expiration_date == 'Never': user_info['acct_expires'] = win32netcon.TIMEQ_FOREVER else: try: dt_obj = salt.utils.dateutils.date_cast(expiration_date) except (ValueError, RuntimeError): return 'Invalid Date/Time Format: {0}'.format(expiration_date) user_info['acct_expires'] = time.mktime(dt_obj.timetuple()) if expired is not None: if expired: user_info['password_expired'] = 1 else: user_info['password_expired'] = 0 if account_disabled is not None: if account_disabled: user_info['flags'] |= win32netcon.UF_ACCOUNTDISABLE else: user_info['flags'] &= ~win32netcon.UF_ACCOUNTDISABLE if unlock_account is not None: if unlock_account: user_info['flags'] &= ~win32netcon.UF_LOCKOUT if password_never_expires is not None: if password_never_expires: user_info['flags'] |= win32netcon.UF_DONT_EXPIRE_PASSWD else: user_info['flags'] &= ~win32netcon.UF_DONT_EXPIRE_PASSWD if disallow_change_password is not None: if disallow_change_password: user_info['flags'] |= win32netcon.UF_PASSWD_CANT_CHANGE else: user_info['flags'] &= ~win32netcon.UF_PASSWD_CANT_CHANGE # Apply new settings try: win32net.NetUserSetInfo(None, name, 4, user_info) except win32net.error as exc: (number, context, message) = exc log.error('Failed to update user {0}'.format(name)) log.error('nbr: {0}'.format(exc.winerror)) log.error('ctx: {0}'.format(exc.funcname)) log.error('msg: {0}'.format(exc.strerror)) return False return True
def update(name, password=None, fullname=None, description=None, home=None, homedrive=None, logonscript=None, profile=None): r''' Updates settings for the windows user. Name is the only required parameter. Settings will only be changed if the parameter is passed a value. .. versionadded:: 2015.8.0 :param name: str The user name to update. :param password: str New user password in plain text. :param fullname: str The user's full name. :param description: str A brief description of the user account. :param home: str The path to the user's home directory. :param homedrive: str The drive letter to assign to the home directory. Must be the Drive Letter followed by a colon. ie: U: :param logonscript: str The path to the logon script. :param profile: str The path to the user's profile directory. :return: bool True if successful. False is unsuccessful. CLI Example: .. code-block:: bash salt '*' user.update bob password=secret profile=C:\Users\Bob home=\\server\homeshare\bob homedrive=U: ''' # Make sure the user exists # Return an object containing current settings for the user try: user_info = win32net.NetUserGetInfo(None, name, 4) except win32net.error as exc: (number, context, message) = exc log.error('Failed to update user {0}'.format(name)) log.error('nbr: {0}'.format(number)) log.error('ctx: {0}'.format(context)) log.error('msg: {0}'.format(message)) return False # Check parameters to update # Update the user object with new settings if password: user_info['password'] = password if home: user_info['home_dir'] = home if homedrive: user_info['home_dir_drive'] = homedrive if description: user_info['comment'] = description if logonscript: user_info['script_path'] = logonscript if fullname: user_info['full_name'] = fullname if profile: user_info['profile'] = profile # Apply new settings try: win32net.NetUserSetInfo(None, name, 4, user_info) except win32net.error as exc: (number, context, message) = exc log.error('Failed to update user {0}'.format(name)) log.error('nbr: {0}'.format(number)) log.error('ctx: {0}'.format(context)) log.error('msg: {0}'.format(message)) return False return True
def createOpsiSetupUser(self, admin=True, delete_existing=False): # pylint: disable=no-self-use,too-many-branches # https://bugs.python.org/file46988/issue.py user_info = { "name": OPSI_SETUP_USER_NAME, "full_name": "opsi setup user", "comment": "auto created by opsi", "password": f"/{''.join((random.choice(string.ascii_letters + string.digits) for i in range(8)))}?", "priv": win32netcon.USER_PRIV_USER, "flags": win32netcon.UF_NORMAL_ACCOUNT | win32netcon.UF_SCRIPT | win32netcon.UF_DONT_EXPIRE_PASSWD } # Test if user exists user_sid = None try: win32net.NetUserGetInfo(None, user_info["name"], 1) user_sid = win32security.ConvertSidToStringSid( win32security.LookupAccountName(None, user_info["name"])[0]) logger.info("User '%s' exists, sid is '%s'", user_info["name"], user_sid) except Exception as err: # pylint: disable=broad-except logger.info(err) self.cleanup_opsi_setup_user( keep_sid=None if delete_existing else user_sid) if delete_existing: user_sid = None # Hide user from login try: winreg.CreateKeyEx( winreg.HKEY_LOCAL_MACHINE, r'Software\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts', 0, winreg.KEY_WOW64_64KEY | winreg.KEY_ALL_ACCESS # sysnative ) except WindowsError: # pylint: disable=undefined-variable pass try: winreg.CreateKeyEx( winreg.HKEY_LOCAL_MACHINE, r'Software\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList', 0, winreg.KEY_WOW64_64KEY | winreg.KEY_ALL_ACCESS # sysnative ) except WindowsError: # pylint: disable=undefined-variable pass with winreg.OpenKey( winreg.HKEY_LOCAL_MACHINE, r'Software\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList', 0, winreg.KEY_SET_VALUE | winreg.KEY_WOW64_64KEY # sysnative ) as reg_key: winreg.SetValueEx(reg_key, user_info["name"], 0, winreg.REG_DWORD, 0) if user_sid: logger.info("Updating password of user '%s'", user_info["name"]) user_info_update = win32net.NetUserGetInfo(None, user_info["name"], 1) user_info_update["password"] = user_info["password"] win32net.NetUserSetInfo(None, user_info["name"], 1, user_info_update) else: logger.info("Creating user '%s'", user_info["name"]) win32net.NetUserAdd(None, 1, user_info) user_sid = win32security.ConvertSidToStringSid( win32security.LookupAccountName(None, user_info["name"])[0]) subprocess.run([ "icacls", os.path.dirname(sys.argv[0]), "/grant:r", f"*{user_sid}:(OI)(CI)RX" ], check=False) subprocess.run([ "icacls", os.path.dirname(config.get("global", "log_file")), "/grant:r", f"*{user_sid}:(OI)(CI)F" ], check=False) subprocess.run([ "icacls", os.path.dirname(config.get("global", "tmp_dir")), "/grant:r", f"*{user_sid}:(OI)(CI)F" ], check=False) local_admin_group_sid = win32security.ConvertStringSidToSid( "S-1-5-32-544") local_admin_group_name = win32security.LookupAccountSid( None, local_admin_group_sid)[0] try: if admin: logger.info("Adding user '%s' to admin group", user_info["name"]) win32net.NetLocalGroupAddMembers( None, local_admin_group_name, 3, [{ "domainandname": user_info["name"] }]) else: logger.info("Removing user '%s' from admin group", user_info["name"]) win32net.NetLocalGroupDelMembers(None, local_admin_group_name, [user_info["name"]]) except pywintypes.error as err: # 1377 - ERROR_MEMBER_NOT_IN_ALIAS # The specified account name is not a member of the group. # 1378 # ERROR_MEMBER_IN_ALIAS # The specified account name is already a member of the group. if err.winerror not in (1377, 1378): raise user_info_4 = win32net.NetUserGetInfo(None, user_info["name"], 4) user_info_4["password"] = user_info["password"] return user_info_4
def create_local_admin_account(user_name, full_name, password): # Create local admin account ret = True admin = None try: p("}}yn\tAdding Admin account (" + user_name + ")...}}xx") accounts.User.create(user_name, password) # p("}}yn\t\tDone.}}xx") # except pywintypes.error as err: except Exception as err: if err.args[2] == "The account already exists.": pass else: # Unexpected error p("}}rb" + str(err) + "}}xx") ret = False # Get the student object admin = accounts.user(user_name) # Set properties for this student # win32net.NetUserChangePassword(None, user_name, old_pw, password) user_data = dict() user_data['name'] = user_name user_data['full_name'] = full_name user_data['password'] = password user_data[ 'flags'] = win32netcon.UF_NORMAL_ACCOUNT | win32netcon.UF_PASSWD_CANT_CHANGE | win32netcon.UF_DONT_EXPIRE_PASSWD | win32netcon.UF_SCRIPT user_data['priv'] = win32netcon.USER_PRIV_ADMIN user_data['comment'] = 'OPE Admin Account' # user_data['home_dir'] = home_dir # user_data['home_dir_drive'] = "h:" user_data['primary_group_id'] = ntsecuritycon.DOMAIN_GROUP_RID_USERS user_data['password_expired'] = 0 user_data['acct_expires'] = win32netcon.TIMEQ_FOREVER win32net.NetUserSetInfo(None, user_name, 3, user_data) # Add user to the required groups p("}}yn\tAdding user to Administrators group...}}xx") grp = accounts.LocalGroup(accounts.group("Administrators").sid) users_grp = accounts.LocalGroup(accounts.group("Users").sid) try: # Add to administrators group grp.add(admin) # except pywintypes.error as err: except Exception as err: if err.args[ 2] == "The specified account name is already a member of the group.": pass else: # Unexpected error p("}}rb" + str(err) + "}}xx") ret = False try: # Add to users group users_grp.add(admin) # except pywintypes.error as err: except Exception as err: if err.args[ 2] == "The specified account name is already a member of the group.": pass else: # Unexpected error p("}}rb" + str(err) + "}}xx") ret = False return ret
def disable_account(account_name): user_data = dict() user_data['flags'] = win32netcon.UF_SCRIPT | win32netcon.UF_ACCOUNTDISABLE win32net.NetUserSetInfo(None, account_name, 1008, user_data)
def rename(self, old_name, new_name): super(QubesWniVmStorage, self).rename(old_name, new_name) user_data = {} user_data['name'] = self._get_username(new_name) win32net.NetUserSetInfo(None, self._get_username(old_name), 0, user_data)
def create_local_student_account(user_name=None, full_name=None, password=None): ret = True # Make sure we have parameters if user_name is None: user_name = util.get_param(2, None) if full_name is None: full_name = util.get_param(3, None) if password is None: password = util.get_param(4, None) if user_name is None or full_name is None or password is None: p("}}rbError - Invalid parameters to create new student user!}}xx", debug_level=1) return False # Create local student account try: p("}}yn\tAdding student account (" + user_name + ")...}}xx") accounts.User.create(user_name, password) # except pywintypes.error as ex: except Exception as ex: if ex.args[2] == "The account already exists.": pass else: # Unexpected error p("}}rb" + str(ex) + "}}xx") ret = False # Set info for the student user_data = dict() user_data['name'] = user_name user_data['full_name'] = full_name # Start w a random complex password user_data['password'] = UserAccounts.generate_random_password( ) # password # NOTE - Student accounts are always created disabled! user_data['flags'] = UserAccounts.DISABLE_ACCOUNT_FLAGS user_data['priv'] = win32netcon.USER_PRIV_USER user_data['comment'] = 'OPE Student Account' # user_data['home_dir'] = home_dir # user_data['home_dir_drive'] = "h:" user_data['primary_group_id'] = ntsecuritycon.DOMAIN_GROUP_RID_USERS user_data['password_expired'] = 0 user_data['acct_expires'] = win32netcon.TIMEQ_FOREVER win32net.NetUserSetInfo(None, user_name, 3, user_data) # Make sure the password is complex enough tmp_password = password if len(tmp_password) < 8: p("}}rbStudent Password Too Short! Padding with !s to 8 characters}}xx" ) pad_chars = (8 - len(tmp_password)) * "!" # Set the password try: user_data['password'] = tmp_password win32net.NetUserSetInfo(None, user_name, 3, user_data) except Exception as ex: p("}}rbERROR setting password for " + user_name + "}}xx\n" + str(ex)) # Add student to the students group p("}}yn\tAdding student to students group...}}xx") if not UserAccounts.set_default_groups_for_student(user_name): ret = False return ret
def update(name, password=None, fullname=None, description=None, home=None, homedrive=None, logonscript=None, profile=None, expiration_date=None, expired=None, account_disabled=None, unlock_account=None, password_never_expires=None, disallow_change_password=None): r''' Updates settings for the windows user. Name is the only required parameter. Settings will only be changed if the parameter is passed a value. .. versionadded:: 2015.8.0 :param str name: The user name to update. :param str password: New user password in plain text. :param str fullname: The user's full name. :param str description: A brief description of the user account. :param str home: The path to the user's home directory. :param str homedrive: The drive letter to assign to the home directory. Must be the Drive Letter followed by a colon. ie: U: :param str logonscript: The path to the logon script. :param str profile: The path to the user's profile directory. :param date expiration_date: The date and time when the account expires. Can be a valid date/time string. To set to never expire pass the string 'Never'. :param bool expired: Pass `True` to expire the account. The user will be prompted to change their password at the next logon. Pass `False` to mark the account as 'not expired'. You can't use this to negate the expiration if the expiration was caused by the account expiring. You'll have to change the `expiration_date` as well. :param bool account_disabled: True disables the account. False enables the account. :param bool unlock_account: True unlocks a locked user account. False is ignored. :param bool password_never_expires: True sets the password to never expire. False allows the password to expire. :param bool disallow_change_password: True blocks the user from changing the password. False allows the user to change the password. :return: True if successful. False is unsuccessful. :rtype: bool CLI Example: .. code-block:: bash salt '*' user.update bob password=secret profile=C:\Users\Bob home=\\server\homeshare\bob homedrive=U: ''' # Make sure the user exists # Return an object containing current settings for the user try: user_info = win32net.NetUserGetInfo(None, name, 4) except win32net.error as exc: (number, context, message) = exc log.error('Failed to update user {0}'.format(name)) log.error('nbr: {0}'.format(number)) log.error('ctx: {0}'.format(context)) log.error('msg: {0}'.format(message)) return False # Check parameters to update # Update the user object with new settings if password: user_info['password'] = password if home: user_info['home_dir'] = home if homedrive: user_info['home_dir_drive'] = homedrive if description: user_info['comment'] = description if logonscript: user_info['script_path'] = logonscript if fullname: user_info['full_name'] = fullname if profile: user_info['profile'] = profile if expiration_date: if expiration_date == 'Never': user_info['acct_expires'] = win32netcon.TIMEQ_FOREVER else: date_format = _get_date_time_format(expiration_date) if date_format: dt_obj = datetime.strptime(expiration_date, date_format) else: return 'Invalid start_date' user_info['acct_expires'] = time.mktime(dt_obj.timetuple()) if expired is not None: if expired: user_info['password_expired'] = 1 else: user_info['password_expired'] = 0 if account_disabled is not None: if account_disabled: user_info['flags'] |= win32netcon.UF_ACCOUNTDISABLE else: user_info['flags'] ^= win32netcon.UF_ACCOUNTDISABLE if unlock_account is not None: if unlock_account: user_info['flags'] ^= win32netcon.UF_LOCKOUT if password_never_expires is not None: if password_never_expires: user_info['flags'] |= win32netcon.UF_DONT_EXPIRE_PASSWD else: user_info['flags'] ^= win32netcon.UF_DONT_EXPIRE_PASSWD if disallow_change_password is not None: if disallow_change_password: user_info['flags'] |= win32netcon.UF_PASSWD_CANT_CHANGE else: user_info['flags'] ^= win32netcon.UF_PASSWD_CANT_CHANGE # Apply new settings try: win32net.NetUserSetInfo(None, name, 4, user_info) except win32net.error as exc: (number, context, message) = exc log.error('Failed to update user {0}'.format(name)) log.error('nbr: {0}'.format(number)) log.error('ctx: {0}'.format(context)) log.error('msg: {0}'.format(message)) return False return True