开发语言:VC
支持平台:Windows XP/Vista/Win7
版本历史:
V1.1 2010年09月19日
- 增加函数AccountIsEmptyPassword,用于判断用户密码是否为空。
V1.0 2010年09月13日
- 完成正式版本。
功能描述:
接口函数:
下载地址:
SetX.zip
源代码:
SetX.h
/* ---------------------------------------------------------- 文件名称:SetX.h 作者:秦建辉 MSN:[email protected] 版本历史: V1.1 2010年09月19日 增加函数AccountIsEmptyPassword,用于判断用户密码是否为空 V1.0 2010年09月13日 完成正式版本。 功能描述: 获取本地时区显示名 获取系统时区(已排序集合) 判断时区是否实行夏令时 设置本地时区 更改计算机名和计算机描述 增加用户帐户 禁用用户帐户 用户密码是否为空 校验计算机名 校验用户帐户名 重启电脑 接口函数: GetLocalTimeZoneDisplayName GetSystemTimeZones TimeZoneIsDaylightSavingTime SetLocalTimeZoneByKeyName SetComputerNameAndDescription AddUserAccount DisableUserAccount AccountIsEmptyPassword ValidateComputerName ValidateUserAccount GetMaxComputerNameLength GetMaxUserAccountLength GetMaxPasswordLength GetMaxCommentLength RebootComputer ------------------------------------------------------------ */ #pragma once #include <windows.h> #include <tchar.h> #include <LM.h> #include <map> using namespace std; // 时区显示名类型定义 typedef struct _TimeZoneDisplayName { TCHAR Name[128]; // 重载小于关系符,使显示名按汉字拼音排序 BOOL operator <(const _TimeZoneDisplayName &A) const { // 提取时差 TCHAR *s1; TCHAR *s2; LONG h1, h2, m1, m2; // 从显示名中提取小时数 h1 = _tcstol(Name + 4, &s1, 10); h2 = _tcstol(A.Name + 4, &s2, 10); if (h1 < h2) return TRUE; else if (h1 > h2) return FALSE; // 从显示名中提取分钟数 if(*s1 == TEXT(':')) m1 = _tcstol(s1 + 1, NULL, 10); else m1 = 0; if(*s2 == TEXT(':')) m2 = _tcstol(s2 + 1, NULL, 10); else m2 = 0; if (h1 < 0) { // 负时区 if (m1 > m2)return TRUE; else if (m1 < m2)return FALSE; } else { // 正时区 if (m1 < m2)return TRUE; else if (m1 > m2)return FALSE; } // 同一时区,则按汉字拼音排序 return (_tcscoll(Name, A.Name) < 0); } } TimeZoneDisplayName; // 时区标识符类型定义 typedef struct _TimeZoneKeyName { TCHAR Name[128]; } TimeZoneKeyName; #ifdef __cplusplus extern "C" { #endif /* 功能:获取本地时区显示名及当前是否是夏令时 参数说明: pDisplayName:输出,存储时区显示名 isDaylightSavingTime:输出,是否夏时制 返回值: 成功: TIME_ZONE_ID_UNKNOWN TIME_ZONE_ID_STANDARD TIME_ZONE_ID_DAYLIGHT 失败: TIME_ZONE_ID_INVALID */ DWORD WINAPI GetLocalTimeZoneDisplayName(TimeZoneDisplayName *pDisplayName, BOOL &isDaylightSavingTime); /* 功能:返回时区信息在本地系统上可用的所有时区的已排序集合 参数说明: pMapTimeZones:map对象指针,键值为时区显示名,值为时区标识符。 返回值: TRUE:成功 FALSE:失败 */ BOOL WINAPI GetSystemTimeZones(map<TimeZoneDisplayName, TimeZoneKeyName>* pMapTimeZones); /* 功能:判断时区是否实行夏令时 参数说明: szTimeZoneKeyName:时区标识符 返回值: TRUE:该时区实行夏令时 FALSE:该时区未实行夏令时 */ BOOL WINAPI TimeZoneIsDaylightSavingTime(const TCHAR* szTimeZoneKeyName); /* 功能:根据时区标识符设置本地时区 参数说明: szTimeZoneKeyName:时区标识符 isDaylightSavingTime:是否夏时制 返回值: TRUE:成功 FALSE:失败 */ BOOL WINAPI SetLocalTimeZoneByKeyName(const TCHAR* szTimeZoneKeyName, BOOL isDaylightSavingTime); /* 功能:设置计算机名及计算机描述 参数说明: szComputerName:要设置的计算机名,可以为NULL。 szDescription:要设置的计算机描述,可以为NULL。 返回值: -1:设置计算机名失败 -2:设置计算机描述失败 0:成功 说明: 要求有管理员权限,并且重新启动计算机后才有效 */ INT WINAPI SetComputerNameAndDescription(const TCHAR* szComputerName, const TCHAR* szDescription); /* 功能:添加计算机用户帐户 参数说明: szName:要增加的用户帐户 szPassword:帐户密码 szComment:注释 szGroupName:要加入的组名 返回值: 错误代码 */ NET_API_STATUS WINAPI AddUserAccount(const TCHAR* szName, const TCHAR* szPassword, const TCHAR* szComment, const TCHAR* szGroupName); /* 功能:禁用计算机用户帐户 参数说明: szName:要禁用的用户帐户 返回值: 错误代码 */ NET_API_STATUS WINAPI DisableUserAccount(const TCHAR* szName); /* 功能:判断用户密码是否为空 参数说明: domainname:主机名,如果为NULL,则为当前登录的计算机 username:要测试的用户帐户,如果为NULL,则为当前登录的用户 返回值: 1:用户密码为空 0:用户密码不为空 -1:其它错误,可能的错误有 ERROR_ACCESS_DENIED NERR_InvalidComputer NERR_NotPrimary NERR_UserNotFound */ INT AccountIsEmptyPassword(const WCHAR* domainname, const WCHAR* username); /* 功能:验证计算机名是否合法 参数说明: szName:要验证的计算机名 返回值: TRUE:计算机名符合规范 FALSE:计算机名不符合规范 说明: 计算机名不超过15个字符,且必须是字母、数字及连字符(-),并且不能全是数字 */ BOOL WINAPI ValidateComputerName(const TCHAR* szName); /* 功能:验证用户帐号名是否合法 参数说明: szName:要验证的用户名 返回值: TRUE:用户名符合规范 FALSE:用户名不符合规范 说明: 用户名不超过20个字符,且必须为可打印字符,不能包含【,"//[]:|<>+=;?*】,也不能全是空格字符 */ BOOL WINAPI ValidateUserAccount(const TCHAR* szName); /* 功能:获取计算机名最大长度 返回值: 计算机名最大长度(15) */ INT WINAPI GetMaxComputerNameLength(void); /* 功能:获得最大用户帐号长度 返回值: 最大用户帐号长度(20) */ INT WINAPI GetMaxUserAccountLength(void); /* 功能:获得最大密码长度(字节数) 返回值: 用户帐号允许的最大密码长度(256字节) 说明: 英文密码允许256个字符,汉字密码允许128个字符 */ INT WINAPI GetMaxPasswordLength(void); /* 功能:获得最大用户帐户注释长度 返回值: 注释、用户帐户注释、计算机全名最大长度(256) */ INT WINAPI GetMaxCommentLength(void); /* 功能:重启计算机 返回值: TRUE:操作成功 FALSE:操作失败 */ BOOL WINAPI RebootComputer(void); #ifdef __cplusplus } #endif
SetX.cpp
#include "SetX.h" #include <strsafe.h> #pragma comment(lib, "Netapi32.lib") typedef struct _REG_TZI_FORMAT { LONG Bias; LONG StandardBias; LONG DaylightBias; SYSTEMTIME StandardDate; SYSTEMTIME DaylightDate; } REG_TZI_FORMAT; // 获取本地时区显示名及当前是否是夏令时 DWORD WINAPI GetLocalTimeZoneDisplayName(TimeZoneDisplayName *pDisplayName, BOOL &isDaylightSavingTime) { DYNAMIC_TIME_ZONE_INFORMATION tzi; DWORD dwStatus; dwStatus = GetDynamicTimeZoneInformation(&tzi); if (dwStatus != TIME_ZONE_ID_INVALID) { // 是否夏时制时间 isDaylightSavingTime = !tzi.DynamicDaylightTimeDisabled; // 查询注册表获取时区显示名 if (pDisplayName != NULL) { HKEY hKey; TCHAR szSubKey[256]; DWORD dwByteLen; StringCchCopy(szSubKey, 256, TEXT("Software//Microsoft//Windows NT//CurrentVersion//Time Zones//")); StringCchCat(szSubKey, 256, tzi.TimeZoneKeyName); RegOpenKeyEx(HKEY_LOCAL_MACHINE, szSubKey, 0, KEY_QUERY_VALUE, &hKey); // 时区显示名 dwByteLen = sizeof(TimeZoneDisplayName); RegQueryValueEx(hKey, TEXT("Display"), NULL, NULL, reinterpret_cast<LPBYTE>(pDisplayName), &dwByteLen); RegCloseKey(hKey); } } return dwStatus; } // 返回时区信息在本地系统上可用的所有时区的已排序集合 BOOL WINAPI GetSystemTimeZones(map<TimeZoneDisplayName, TimeZoneKeyName>* pMapTimeZones) { const TCHAR* TimeZonesRegistryEntry = TEXT("Software//Microsoft//Windows NT//CurrentVersion//Time Zones"); // 检测参数 if (pMapTimeZones == NULL)return FALSE; // 清空map表 pMapTimeZones->clear(); HKEY hKey; LONG ErrorCode; DWORD dwCchSize, dwIndex; TCHAR szSubKey[256]; INT InsertPoint; TimeZoneDisplayName szDisplayName; TimeZoneKeyName szKeyName; // 打开注册表时区入口 ErrorCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TimeZonesRegistryEntry, 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hKey); if (ErrorCode != ERROR_SUCCESS) { return FALSE; } StringCchCopy(szSubKey, 256, TimeZonesRegistryEntry); StringCchCat(szSubKey, 256, TEXT("//")); InsertPoint = _tcslen(szSubKey); for (dwIndex = 0; ; dwIndex++) { // 枚举所有时区标识符 dwCchSize = 128; ErrorCode = RegEnumKeyEx(hKey, dwIndex, szKeyName.Name, &dwCchSize, NULL, NULL, NULL, NULL); if (ErrorCode == ERROR_NO_MORE_ITEMS)break; if (ErrorCode == ERROR_SUCCESS) { HKEY hSubKey; szSubKey[InsertPoint] = 0; StringCchCat(szSubKey, 256, szKeyName.Name); ErrorCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szSubKey, 0, KEY_QUERY_VALUE, &hSubKey); if (ErrorCode == ERROR_SUCCESS) { // 获取时区显示名 DWORD dwByteLen = sizeof(szDisplayName); ErrorCode = RegQueryValueEx(hSubKey, TEXT("Display"), NULL, NULL, reinterpret_cast<LPBYTE>(&szDisplayName), &dwByteLen); RegCloseKey(hSubKey); if (ErrorCode == ERROR_SUCCESS) { pMapTimeZones->insert(make_pair(szDisplayName, szKeyName)); } } } } RegCloseKey(hKey); return TRUE; } // 判断该时区是否实行夏时制 BOOL WINAPI TimeZoneIsDaylightSavingTime(const TCHAR* szTimeZoneKeyName) { HKEY hKey; LONG ErrorCode; TCHAR szSubKey[256]; StringCchCopy(szSubKey, 256, TEXT("Software//Microsoft//Windows NT//CurrentVersion//Time Zones//")); StringCchCat(szSubKey, 256, szTimeZoneKeyName); StringCchCat(szSubKey, 256, TEXT("//Dynamic DST")); ErrorCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szSubKey, 0, KEY_QUERY_VALUE, &hKey); if (ErrorCode == ERROR_SUCCESS) { RegCloseKey(hKey); return TRUE; } return FALSE; } // 根据时区标识符设置本地时区 BOOL WINAPI SetLocalTimeZoneByKeyName(const TCHAR* szTimeZoneKeyName, BOOL isDaylightSavingTime) { HKEY hKey; LONG ErrorCode; TCHAR szSubKey[256]; TCHAR szStandardName[32]; TCHAR szDaylightName[32]; REG_TZI_FORMAT regTZI; DWORD dwByteLen; // 检测入口参数 if ((szTimeZoneKeyName == NULL) || (_tcslen(szTimeZoneKeyName) == 0)) { // 时区标识符不能为空 return FALSE; } StringCchCopy(szSubKey, 256, TEXT("Software//Microsoft//Windows NT//CurrentVersion//Time Zones//")); StringCchCat(szSubKey, 256, szTimeZoneKeyName); ErrorCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szSubKey, 0, KEY_QUERY_VALUE, &hKey); if (ErrorCode != ERROR_SUCCESS) { return FALSE; } // 标准名 dwByteLen = sizeof(szStandardName); ErrorCode = RegQueryValueEx(hKey, TEXT("Std"), NULL, NULL, reinterpret_cast<LPBYTE>(&szStandardName), &dwByteLen); if (ErrorCode != ERROR_SUCCESS) { RegCloseKey(hKey); return FALSE; } // 夏时制名 dwByteLen = sizeof(szDaylightName); ErrorCode = RegQueryValueEx(hKey, TEXT("Dlt"), NULL, NULL, reinterpret_cast<LPBYTE>(&szDaylightName), &dwByteLen); if (ErrorCode != ERROR_SUCCESS) { RegCloseKey(hKey); return FALSE; } // 时区信息 dwByteLen = sizeof(regTZI); ErrorCode = RegQueryValueEx(hKey, TEXT("TZI"), NULL, NULL, reinterpret_cast<LPBYTE>(®TZI), &dwByteLen); RegCloseKey(hKey); if ((ErrorCode != ERROR_SUCCESS) || (dwByteLen > sizeof(regTZI))) { return FALSE; } // 开启权限 HANDLE hToken; TOKEN_PRIVILEGES tkp; BOOL isOK; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &hToken)) { return FALSE; } LookupPrivilegeValue(NULL, SE_TIME_ZONE_NAME, &tkp.Privileges[0].Luid); tkp.PrivilegeCount = 1; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0); if (GetLastError() != ERROR_SUCCESS) { CloseHandle(hToken); return FALSE; } // 设置新时区 DYNAMIC_TIME_ZONE_INFORMATION tzi; tzi.Bias = regTZI.Bias; StringCchCopy(tzi.StandardName, 32, szStandardName); tzi.StandardDate = regTZI.StandardDate; tzi.StandardBias = regTZI.StandardBias; StringCchCopy(tzi.DaylightName, 32, szDaylightName); tzi.DaylightDate = regTZI.DaylightDate; tzi.DaylightBias = regTZI.DaylightBias; StringCchCopy(tzi.TimeZoneKeyName, 128, szTimeZoneKeyName); tzi.DynamicDaylightTimeDisabled = !isDaylightSavingTime; isOK = SetDynamicTimeZoneInformation( &tzi ); // 设置动态时区 // 关闭权限 tkp.Privileges[0].Attributes = 0; AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0); CloseHandle(hToken); return isOK; } // 设置计算机名及计算机描述 INT WINAPI SetComputerNameAndDescription(const TCHAR* szComputerName, const TCHAR* szDescription) { if ((szComputerName != NULL) && (_tcslen(szComputerName) != 0)) // 计算机名不能为空 { // 设置计算名要求有管理员权限。改名成功后,重新启动计算机后才有效 if (!::SetComputerNameEx(ComputerNamePhysicalDnsHostname, szComputerName)) { // 更改计算机名失败 return -1; } } if (szDescription != NULL) // 计算机描述可以为空 { // 更改计算机描述。要求有管理员权限。 TCHAR szCommandLine[512]; HINSTANCE hInstance; StringCchCopy(szCommandLine, sizeof(szCommandLine)/sizeof(TCHAR), TEXT("/c net config server /SRVCOMMENT:/"")); StringCchCat(szCommandLine, sizeof(szCommandLine)/sizeof(TCHAR), szDescription); StringCchCat(szCommandLine, sizeof(szCommandLine)/sizeof(TCHAR), TEXT("/"")); hInstance = ShellExecute(NULL, NULL, TEXT("cmd.exe"), szCommandLine, NULL, SW_HIDE); if (reinterpret_cast<int>(hInstance) <= 32) { // 更改计算机描述失败 return -2; } } return 0; } // 添加用户帐户并加入指定组 NET_API_STATUS WINAPI AddUserAccount(const TCHAR* szName, const TCHAR* szPassword, const TCHAR* szComment, const TCHAR* szGroupName) { USER_INFO_1 ui = {0}; // 预先初始化 NET_API_STATUS nStatus; if ((szName == NULL) || (_tcslen(szName) == 0)) { // 用户名不能为空 return ERROR_INVALID_PARAMETER; } ui.usri1_name = const_cast<TCHAR*>(szName); ui.usri1_password = const_cast<TCHAR*>(szPassword); ui.usri1_comment = const_cast<TCHAR*>(szComment); ui.usri1_priv = USER_PRIV_USER; ui.usri1_flags = UF_SCRIPT | UF_DONT_EXPIRE_PASSWD; // 开机登录用户名 // 添加用户帐户 nStatus = NetUserAdd(NULL, 1, reinterpret_cast<LPBYTE>(&ui), NULL); if (nStatus == NERR_Success) { // 将用户加入组 if ((szGroupName != NULL) && (_tcslen(szGroupName) != 0)) { LOCALGROUP_MEMBERS_INFO_3 lgmi; lgmi.lgrmi3_domainandname = const_cast<TCHAR*>(szName); nStatus = NetLocalGroupAddMembers(NULL, szGroupName, 3, reinterpret_cast<LPBYTE>(&lgmi), 1); } } return nStatus; } // 禁用用户帐号 NET_API_STATUS WINAPI DisableUserAccount(const TCHAR* szName) { if ((szName == NULL) || (_tcslen(szName) == 0)) { // 用户名不能为空 return ERROR_INVALID_PARAMETER; } NET_API_STATUS nStatus; LPUSER_INFO_1 pBuf = NULL; nStatus = NetUserGetInfo(NULL, szName, 1, reinterpret_cast<LPBYTE*>(&pBuf)); if (nStatus == NERR_Success) { USER_INFO_1008 ui; ui.usri1008_flags = (*pBuf).usri1_flags | UF_ACCOUNTDISABLE; nStatus = NetUserSetInfo(NULL, szName, 1008, reinterpret_cast<LPBYTE>(&ui), NULL); } if (pBuf != NULL) { NetApiBufferFree(pBuf); } return nStatus; } // 判断用户密码是否为空 INT AccountIsEmptyPassword(const WCHAR* domainname, const WCHAR* username) { NET_API_STATUS dwStatus; dwStatus = NetUserChangePassword(domainname, username, L"", L""); if ((dwStatus == NERR_Success) || (dwStatus == NERR_PasswordTooShort)) { // 密码为空 return 1; } else if(dwStatus == ERROR_INVALID_PASSWORD) { // 密码不为空 return 0; } else { // 其它错误 return -1; } } // 获得最大计算机名长度 INT WINAPI GetMaxComputerNameLength(void) { return MAX_COMPUTERNAME_LENGTH; // 15 } // 获得最大用户帐号长度 INT WINAPI GetMaxUserAccountLength(void) { return LM20_UNLEN; // 20 } // 获得最大用户帐户注释长度 INT WINAPI GetMaxCommentLength(void) { return MAXCOMMENTSZ; // 256 } // 获得最大密码长度(字节数) INT WINAPI GetMaxPasswordLength(void) { return PWLEN; // 256 } // 验证计算机名是否合法 BOOL WINAPI ValidateComputerName(const TCHAR* szName) { // 允许字符白名单 const TCHAR* WHITELIST = TEXT("-"); if (szName == NULL)return FALSE; UINT uiLen = _tcslen(szName); if ((uiLen == 0) || (uiLen > MAX_COMPUTERNAME_LENGTH)) { // 用户名不能超过20个字符 return FALSE; } BOOL isAllDigit = TRUE; for (UINT i = 0; i < uiLen; i++) { TCHAR ch = szName[i]; if (!_istalnum(ch) && (_tcschr(WHITELIST, ch) == NULL)) { // 不是字母数字,也不是白名单字符 return FALSE; } if (isAllDigit) { if (!_istdigit(ch)) { isAllDigit = FALSE; } } } if (isAllDigit) return FALSE; // 计算机名不能全是数字 else return TRUE; } // 验证用户帐号名是否合法 BOOL WINAPI ValidateUserAccount(const TCHAR* szName) { // 禁止字符黑名单 const TCHAR* BLACKLIST = TEXT(",/"///[]:|<>+=;?*"); if (szName == NULL)return FALSE; // 不能是内置帐户 if(_tcsicmp(szName, TEXT("Administrator")) == 0 || _tcsicmp(szName, TEXT("Guest")) == 0) { // 用户帐户不区分大小写 return FALSE; } UINT uiLen = _tcslen(szName); if ((uiLen == 0) || (uiLen > LM20_UNLEN)) { // 用户名不能超过20个字符 return FALSE; } BOOL isAllSpace = TRUE; for (UINT i = 0; i < uiLen; i++) { TCHAR ch = szName[i]; if (ch < TEXT(' ')) { // 用户名不能是非打印字符 return FALSE; } else if (_tcschr(BLACKLIST, ch) != NULL) { // 不能含有黑名单字符 return FALSE; } if (isAllSpace) { if (ch != TEXT(' ')) { isAllSpace = FALSE; } } } if (isAllSpace) return FALSE; // 用户名不能全是空格组成 else return TRUE; } // 重启计算机 BOOL WINAPI RebootComputer(void) { HANDLE hToken; TOKEN_PRIVILEGES tkp; // 访问令牌 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { return FALSE; } // 设置权限 LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid); tkp.PrivilegeCount = 1; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; // 调整权限 AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0); if (GetLastError() != ERROR_SUCCESS) { CloseHandle(hToken); return FALSE; } // 关机重启 return ExitWindowsEx(EWX_REBOOT | EWX_FORCEIFHUNG, SHTDN_REASON_MAJOR_APPLICATION | SHTDN_REASON_MINOR_MAINTENANCE | SHTDN_REASON_FLAG_PLANNED); }