2014-10-23 18:36:11 +00:00
|
|
|
/*
|
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS net command
|
2015-09-09 13:13:35 +00:00
|
|
|
* FILE: base/applications/network/net/cmdUser.c
|
2014-10-23 18:36:11 +00:00
|
|
|
* PURPOSE:
|
|
|
|
*
|
|
|
|
* PROGRAMMERS: Eric Kohl
|
2016-03-31 21:48:43 +00:00
|
|
|
* Curtis Wilson
|
2014-10-23 18:36:11 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "net.h"
|
|
|
|
|
2019-05-18 12:46:04 +00:00
|
|
|
#define SECONDS_PER_DAY (60 * 60 * 24)
|
|
|
|
#define SECONDS_PER_HOUR (60 * 60)
|
|
|
|
|
2019-03-10 21:00:41 +00:00
|
|
|
typedef struct _COUNTY_TABLE
|
|
|
|
{
|
|
|
|
DWORD dwCountryCode;
|
|
|
|
DWORD dwMessageId;
|
|
|
|
} COUNTRY_TABLE, *PCOUNTRY_TABLE;
|
|
|
|
|
|
|
|
|
2018-07-07 20:06:08 +00:00
|
|
|
static WCHAR szPasswordChars[] = L"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@#$%_-+:";
|
2019-03-10 21:00:41 +00:00
|
|
|
static COUNTRY_TABLE CountryTable[] =
|
|
|
|
{ { 0, 5080}, // System Default
|
|
|
|
{ 1, 5081}, // United States
|
|
|
|
{ 2, 5082}, // Canada (French)
|
|
|
|
{ 3, 5083}, // Latin America
|
|
|
|
{ 31, 5084}, // Netherlands
|
|
|
|
{ 32, 5085}, // Belgium
|
|
|
|
{ 33, 5086}, // France
|
|
|
|
{ 34, 5090}, // Spain
|
|
|
|
{ 39, 5087}, // Italy
|
|
|
|
{ 41, 5088}, // Switzerland
|
|
|
|
{ 44, 5089}, // United Kingdom
|
|
|
|
{ 45, 5091}, // Denmark
|
|
|
|
{ 46, 5092}, // Sweden
|
|
|
|
{ 47, 5093}, // Norway
|
|
|
|
{ 49, 5094}, // Germany
|
|
|
|
{ 61, 5095}, // Australia
|
|
|
|
{ 81, 5096}, // Japan
|
|
|
|
{ 82, 5097}, // Korea
|
|
|
|
{ 86, 5098}, // China (PRC)
|
|
|
|
{ 88, 5099}, // Taiwan
|
|
|
|
{ 99, 5100}, // Asia
|
|
|
|
{351, 5101}, // Portugal
|
|
|
|
{358, 5102}, // Finland
|
|
|
|
{785, 5103}, // Arabic
|
|
|
|
{972, 5104} }; // Hebrew
|
|
|
|
|
2018-07-07 20:06:08 +00:00
|
|
|
|
2014-10-23 18:36:11 +00:00
|
|
|
static
|
|
|
|
int
|
2018-07-07 20:12:37 +00:00
|
|
|
CompareInfo(const void *a, const void *b)
|
2014-10-23 18:36:11 +00:00
|
|
|
{
|
|
|
|
return _wcsicmp(((PUSER_INFO_0)a)->usri0_name,
|
|
|
|
((PUSER_INFO_0)b)->usri0_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static
|
|
|
|
NET_API_STATUS
|
|
|
|
EnumerateUsers(VOID)
|
|
|
|
{
|
|
|
|
PUSER_INFO_0 pBuffer = NULL;
|
|
|
|
PSERVER_INFO_100 pServer = NULL;
|
|
|
|
DWORD dwRead = 0, dwTotal = 0;
|
|
|
|
DWORD i;
|
2018-03-04 15:12:18 +00:00
|
|
|
DWORD ResumeHandle = 0;
|
2014-10-23 18:36:11 +00:00
|
|
|
NET_API_STATUS Status;
|
|
|
|
|
|
|
|
Status = NetServerGetInfo(NULL,
|
|
|
|
100,
|
|
|
|
(LPBYTE*)&pServer);
|
|
|
|
if (Status != NERR_Success)
|
|
|
|
return Status;
|
|
|
|
|
2016-10-07 22:50:32 +00:00
|
|
|
ConPuts(StdOut, L"\n");
|
2019-04-06 13:32:00 +00:00
|
|
|
PrintMessageStringV(4410, pServer->sv100_name);
|
|
|
|
ConPuts(StdOut, L"\n");
|
2014-11-16 10:34:49 +00:00
|
|
|
PrintPadding(L'-', 79);
|
2016-10-07 22:50:32 +00:00
|
|
|
ConPuts(StdOut, L"\n");
|
2014-10-23 18:36:11 +00:00
|
|
|
|
|
|
|
NetApiBufferFree(pServer);
|
|
|
|
|
2016-03-31 21:48:43 +00:00
|
|
|
do
|
2014-10-23 18:36:11 +00:00
|
|
|
{
|
2016-03-31 21:48:43 +00:00
|
|
|
Status = NetUserEnum(NULL,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
(LPBYTE*)&pBuffer,
|
|
|
|
MAX_PREFERRED_LENGTH,
|
|
|
|
&dwRead,
|
|
|
|
&dwTotal,
|
|
|
|
&ResumeHandle);
|
|
|
|
if ((Status != NERR_Success) && (Status != ERROR_MORE_DATA))
|
|
|
|
return Status;
|
|
|
|
|
|
|
|
qsort(pBuffer,
|
|
|
|
dwRead,
|
|
|
|
sizeof(PUSER_INFO_0),
|
2018-07-07 20:12:37 +00:00
|
|
|
CompareInfo);
|
2016-03-31 21:48:43 +00:00
|
|
|
|
|
|
|
for (i = 0; i < dwRead; i++)
|
|
|
|
{
|
|
|
|
if (pBuffer[i].usri0_name)
|
2016-10-07 22:50:32 +00:00
|
|
|
ConPrintf(StdOut, L"%s\n", pBuffer[i].usri0_name);
|
2016-03-31 21:48:43 +00:00
|
|
|
}
|
|
|
|
|
2016-07-13 17:35:16 +00:00
|
|
|
NetApiBufferFree(pBuffer);
|
|
|
|
pBuffer = NULL;
|
2014-10-23 18:36:11 +00:00
|
|
|
}
|
2016-03-31 21:48:43 +00:00
|
|
|
while (Status == ERROR_MORE_DATA);
|
2014-10-23 18:36:11 +00:00
|
|
|
|
|
|
|
return NERR_Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static
|
|
|
|
VOID
|
|
|
|
PrintDateTime(DWORD dwSeconds)
|
|
|
|
{
|
|
|
|
LARGE_INTEGER Time;
|
|
|
|
FILETIME FileTime;
|
|
|
|
SYSTEMTIME SystemTime;
|
|
|
|
WCHAR DateBuffer[80];
|
|
|
|
WCHAR TimeBuffer[80];
|
|
|
|
|
|
|
|
RtlSecondsSince1970ToTime(dwSeconds, &Time);
|
|
|
|
FileTime.dwLowDateTime = Time.u.LowPart;
|
|
|
|
FileTime.dwHighDateTime = Time.u.HighPart;
|
2014-10-28 21:57:41 +00:00
|
|
|
FileTimeToLocalFileTime(&FileTime, &FileTime);
|
2014-10-23 18:36:11 +00:00
|
|
|
FileTimeToSystemTime(&FileTime, &SystemTime);
|
|
|
|
|
|
|
|
GetDateFormatW(LOCALE_USER_DEFAULT,
|
|
|
|
DATE_SHORTDATE,
|
|
|
|
&SystemTime,
|
|
|
|
NULL,
|
|
|
|
DateBuffer,
|
2019-05-18 09:26:02 +00:00
|
|
|
ARRAYSIZE(DateBuffer));
|
2014-10-23 18:36:11 +00:00
|
|
|
|
|
|
|
GetTimeFormatW(LOCALE_USER_DEFAULT,
|
|
|
|
TIME_NOSECONDS,
|
|
|
|
&SystemTime,
|
|
|
|
NULL,
|
|
|
|
TimeBuffer,
|
2019-05-18 09:26:02 +00:00
|
|
|
ARRAYSIZE(TimeBuffer));
|
2014-10-23 18:36:11 +00:00
|
|
|
|
2016-10-07 22:50:32 +00:00
|
|
|
ConPrintf(StdOut, L"%s %s", DateBuffer, TimeBuffer);
|
2014-10-23 18:36:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-05-18 12:46:04 +00:00
|
|
|
static
|
|
|
|
VOID
|
|
|
|
PrintLocalTime(DWORD dwSeconds)
|
|
|
|
{
|
|
|
|
LARGE_INTEGER Time;
|
|
|
|
FILETIME FileTime;
|
|
|
|
SYSTEMTIME SystemTime;
|
|
|
|
WCHAR TimeBuffer[80];
|
|
|
|
|
|
|
|
RtlSecondsSince1970ToTime(dwSeconds, &Time);
|
|
|
|
FileTime.dwLowDateTime = Time.u.LowPart;
|
|
|
|
FileTime.dwHighDateTime = Time.u.HighPart;
|
|
|
|
FileTimeToSystemTime(&FileTime, &SystemTime);
|
|
|
|
|
|
|
|
GetTimeFormatW(LOCALE_USER_DEFAULT,
|
|
|
|
TIME_NOSECONDS,
|
|
|
|
&SystemTime,
|
|
|
|
NULL,
|
|
|
|
TimeBuffer,
|
|
|
|
ARRAYSIZE(TimeBuffer));
|
|
|
|
|
|
|
|
ConPrintf(StdOut, L"%s", TimeBuffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-28 21:57:41 +00:00
|
|
|
static
|
|
|
|
DWORD
|
|
|
|
GetTimeInSeconds(VOID)
|
|
|
|
{
|
|
|
|
LARGE_INTEGER Time;
|
|
|
|
FILETIME FileTime;
|
|
|
|
DWORD dwSeconds;
|
|
|
|
|
|
|
|
GetSystemTimeAsFileTime(&FileTime);
|
|
|
|
Time.u.LowPart = FileTime.dwLowDateTime;
|
|
|
|
Time.u.HighPart = FileTime.dwHighDateTime;
|
|
|
|
RtlTimeToSecondsSince1970(&Time, &dwSeconds);
|
|
|
|
|
|
|
|
return dwSeconds;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-03-10 21:00:41 +00:00
|
|
|
static
|
|
|
|
BOOL
|
|
|
|
GetCountryFromCountryCode(
|
|
|
|
_In_ DWORD dwCountryCode,
|
|
|
|
_In_ DWORD dwCountryLength,
|
|
|
|
_Out_ PWSTR szCountryBuffer)
|
|
|
|
{
|
|
|
|
DWORD i;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAYSIZE(CountryTable); i++)
|
|
|
|
{
|
|
|
|
if (CountryTable[i].dwCountryCode == dwCountryCode)
|
|
|
|
{
|
|
|
|
if (szCountryBuffer != NULL && dwCountryLength > 0)
|
|
|
|
{
|
|
|
|
FormatMessageW(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
|
|
hModuleNetMsg,
|
|
|
|
CountryTable[i].dwMessageId,
|
|
|
|
LANG_USER_DEFAULT,
|
|
|
|
szCountryBuffer,
|
|
|
|
dwCountryLength,
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-05-18 09:26:02 +00:00
|
|
|
static
|
|
|
|
BOOL
|
|
|
|
BitValue(
|
|
|
|
PBYTE pLogonHours,
|
|
|
|
DWORD dwBitNumber)
|
|
|
|
{
|
|
|
|
DWORD dwIndex = dwBitNumber / 8;
|
|
|
|
BYTE Mask = 1 << (dwBitNumber & 7);
|
|
|
|
|
|
|
|
return ((pLogonHours[dwIndex] & Mask) != 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static
|
|
|
|
VOID
|
|
|
|
PrintLogonHours(
|
|
|
|
DWORD dwUnitsPerWeek,
|
|
|
|
PBYTE pLogonHours,
|
|
|
|
INT nPaddedLength)
|
|
|
|
{
|
|
|
|
DWORD dwUnitsPerDay, dwBitNumber, dwSecondsPerUnit;
|
2019-05-18 12:46:04 +00:00
|
|
|
DWORD dwStartTime, dwEndTime, dwStartDay, dwEndDay;
|
2019-05-18 09:26:02 +00:00
|
|
|
BOOL bBitValue, bFirst = TRUE;
|
|
|
|
|
|
|
|
if ((dwUnitsPerWeek == 0) ||
|
|
|
|
((dwUnitsPerWeek %7) != 0))
|
|
|
|
return;
|
|
|
|
|
|
|
|
dwUnitsPerDay = dwUnitsPerWeek / 7;
|
|
|
|
|
|
|
|
if (((dwUnitsPerDay % 24) != 0) ||
|
|
|
|
((dwUnitsPerDay / 24) > 6))
|
|
|
|
return;
|
|
|
|
|
2019-05-18 12:46:04 +00:00
|
|
|
dwSecondsPerUnit = (SECONDS_PER_DAY) / dwUnitsPerDay;
|
2019-05-18 09:26:02 +00:00
|
|
|
|
|
|
|
for (dwBitNumber = 0; dwBitNumber < dwUnitsPerWeek; dwBitNumber++)
|
|
|
|
{
|
|
|
|
bBitValue = BitValue(pLogonHours, dwBitNumber);
|
|
|
|
if (bBitValue)
|
|
|
|
{
|
|
|
|
dwStartTime = dwSecondsPerUnit * dwBitNumber;
|
|
|
|
|
|
|
|
while (bBitValue != 0 && dwBitNumber < dwUnitsPerWeek)
|
|
|
|
{
|
|
|
|
dwBitNumber++;
|
|
|
|
if (dwBitNumber < dwUnitsPerWeek)
|
|
|
|
bBitValue = BitValue(pLogonHours, dwBitNumber);
|
|
|
|
}
|
|
|
|
|
|
|
|
dwEndTime = dwSecondsPerUnit * dwBitNumber;
|
|
|
|
|
|
|
|
if (!bFirst)
|
|
|
|
PrintPadding(L' ', nPaddedLength);
|
|
|
|
|
2019-05-18 12:46:04 +00:00
|
|
|
if (dwStartTime == 0 && dwEndTime == (SECONDS_PER_DAY * 7))
|
2019-05-18 09:26:02 +00:00
|
|
|
{
|
|
|
|
PrintMessageString(4302);
|
|
|
|
ConPuts(StdOut, L"\n");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-05-18 12:46:04 +00:00
|
|
|
dwStartDay = dwStartTime / SECONDS_PER_DAY;
|
|
|
|
dwEndDay = (dwEndTime / SECONDS_PER_DAY) % 7;
|
|
|
|
|
|
|
|
PrintMessageString(4307 + dwStartDay);
|
|
|
|
ConPuts(StdOut, L" ");
|
|
|
|
PrintLocalTime((dwStartTime % SECONDS_PER_DAY) + SECONDS_PER_HOUR);
|
|
|
|
|
|
|
|
ConPrintf(StdOut, L" - ");
|
|
|
|
if (dwStartDay != dwEndDay)
|
|
|
|
{
|
|
|
|
PrintMessageString(4307 + dwEndDay);
|
|
|
|
ConPuts(StdOut, L" ");
|
|
|
|
}
|
|
|
|
|
|
|
|
PrintLocalTime((dwEndTime % SECONDS_PER_DAY) + SECONDS_PER_HOUR);
|
|
|
|
ConPuts(StdOut, L"\n");
|
2019-05-18 09:26:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bFirst = FALSE;
|
|
|
|
}
|
|
|
|
}
|
2019-05-18 19:21:39 +00:00
|
|
|
|
|
|
|
if (bFirst)
|
|
|
|
{
|
|
|
|
/* No logon hours */
|
|
|
|
PrintMessageString(4434);
|
|
|
|
ConPuts(StdOut, L"\n");
|
|
|
|
}
|
2019-05-18 09:26:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-23 18:36:11 +00:00
|
|
|
static
|
|
|
|
NET_API_STATUS
|
|
|
|
DisplayUser(LPWSTR lpUserName)
|
|
|
|
{
|
2014-10-25 21:27:05 +00:00
|
|
|
PUSER_MODALS_INFO_0 pUserModals = NULL;
|
2014-10-23 18:36:11 +00:00
|
|
|
PUSER_INFO_4 pUserInfo = NULL;
|
2014-11-01 19:24:44 +00:00
|
|
|
PLOCALGROUP_USERS_INFO_0 pLocalGroupInfo = NULL;
|
|
|
|
PGROUP_USERS_INFO_0 pGroupInfo = NULL;
|
|
|
|
DWORD dwLocalGroupRead, dwLocalGroupTotal;
|
|
|
|
DWORD dwGroupRead, dwGroupTotal;
|
2014-10-28 21:57:41 +00:00
|
|
|
DWORD dwLastSet;
|
2014-11-01 19:24:44 +00:00
|
|
|
DWORD i;
|
2019-03-10 21:00:41 +00:00
|
|
|
WCHAR szCountry[40];
|
2019-04-06 13:32:00 +00:00
|
|
|
INT nPaddedLength = 36;
|
2014-10-23 18:36:11 +00:00
|
|
|
NET_API_STATUS Status;
|
|
|
|
|
|
|
|
/* Modify the user */
|
|
|
|
Status = NetUserGetInfo(NULL,
|
|
|
|
lpUserName,
|
|
|
|
4,
|
|
|
|
(LPBYTE*)&pUserInfo);
|
|
|
|
if (Status != NERR_Success)
|
|
|
|
return Status;
|
|
|
|
|
2014-10-25 21:27:05 +00:00
|
|
|
Status = NetUserModalsGet(NULL,
|
|
|
|
0,
|
|
|
|
(LPBYTE*)&pUserModals);
|
|
|
|
if (Status != NERR_Success)
|
|
|
|
goto done;
|
|
|
|
|
2014-11-01 19:24:44 +00:00
|
|
|
Status = NetUserGetLocalGroups(NULL,
|
|
|
|
lpUserName,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
(LPBYTE*)&pLocalGroupInfo,
|
|
|
|
MAX_PREFERRED_LENGTH,
|
|
|
|
&dwLocalGroupRead,
|
|
|
|
&dwLocalGroupTotal);
|
|
|
|
if (Status != NERR_Success)
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
Status = NetUserGetGroups(NULL,
|
|
|
|
lpUserName,
|
|
|
|
0,
|
|
|
|
(LPBYTE*)&pGroupInfo,
|
|
|
|
MAX_PREFERRED_LENGTH,
|
|
|
|
&dwGroupRead,
|
|
|
|
&dwGroupTotal);
|
|
|
|
if (Status != NERR_Success)
|
|
|
|
goto done;
|
|
|
|
|
2019-04-06 13:32:00 +00:00
|
|
|
PrintPaddedMessageString(4411, nPaddedLength);
|
2016-10-07 22:50:32 +00:00
|
|
|
ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_name);
|
2014-11-08 21:44:32 +00:00
|
|
|
|
2019-04-06 13:32:00 +00:00
|
|
|
PrintPaddedMessageString(4412, nPaddedLength);
|
2016-10-07 22:50:32 +00:00
|
|
|
ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_full_name);
|
2014-11-08 21:44:32 +00:00
|
|
|
|
2019-04-06 13:32:00 +00:00
|
|
|
PrintPaddedMessageString(4413, nPaddedLength);
|
2016-10-07 22:50:32 +00:00
|
|
|
ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_comment);
|
2014-11-08 21:44:32 +00:00
|
|
|
|
2019-04-06 13:32:00 +00:00
|
|
|
PrintPaddedMessageString(4414, nPaddedLength);
|
2016-10-07 22:50:32 +00:00
|
|
|
ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_usr_comment);
|
2014-11-08 21:44:32 +00:00
|
|
|
|
2019-04-06 13:32:00 +00:00
|
|
|
PrintPaddedMessageString(4416, nPaddedLength);
|
2019-03-10 21:00:41 +00:00
|
|
|
GetCountryFromCountryCode(pUserInfo->usri4_country_code,
|
|
|
|
ARRAYSIZE(szCountry), szCountry);
|
|
|
|
ConPrintf(StdOut, L"%03ld (%s)\n", pUserInfo->usri4_country_code, szCountry);
|
2014-11-08 21:44:32 +00:00
|
|
|
|
2019-04-06 13:32:00 +00:00
|
|
|
PrintPaddedMessageString(4419, nPaddedLength);
|
2014-11-09 13:39:20 +00:00
|
|
|
if (pUserInfo->usri4_flags & UF_ACCOUNTDISABLE)
|
2019-04-08 20:48:06 +00:00
|
|
|
PrintMessageString(4301);
|
2014-11-09 13:39:20 +00:00
|
|
|
else if (pUserInfo->usri4_flags & UF_LOCKOUT)
|
2019-04-06 13:32:00 +00:00
|
|
|
PrintMessageString(4440);
|
2014-11-09 13:39:20 +00:00
|
|
|
else
|
2019-04-08 20:48:06 +00:00
|
|
|
PrintMessageString(4300);
|
2016-10-07 22:50:32 +00:00
|
|
|
ConPuts(StdOut, L"\n");
|
2014-11-08 21:44:32 +00:00
|
|
|
|
2019-04-06 13:32:00 +00:00
|
|
|
PrintPaddedMessageString(4420, nPaddedLength);
|
2014-10-23 18:36:11 +00:00
|
|
|
if (pUserInfo->usri4_acct_expires == TIMEQ_FOREVER)
|
2019-04-08 20:48:06 +00:00
|
|
|
PrintMessageString(4305);
|
2014-10-25 21:27:05 +00:00
|
|
|
else
|
|
|
|
PrintDateTime(pUserInfo->usri4_acct_expires);
|
2016-10-07 22:50:32 +00:00
|
|
|
ConPuts(StdOut, L"\n\n");
|
2014-10-25 21:27:05 +00:00
|
|
|
|
2019-04-06 13:32:00 +00:00
|
|
|
PrintPaddedMessageString(4421, nPaddedLength);
|
2014-10-28 21:57:41 +00:00
|
|
|
dwLastSet = GetTimeInSeconds() - pUserInfo->usri4_password_age;
|
|
|
|
PrintDateTime(dwLastSet);
|
2017-10-29 20:38:05 +00:00
|
|
|
ConPuts(StdOut, L"\n");
|
2014-10-28 21:57:41 +00:00
|
|
|
|
2019-04-06 13:32:00 +00:00
|
|
|
PrintPaddedMessageString(4422, nPaddedLength);
|
2014-10-28 21:57:41 +00:00
|
|
|
if ((pUserInfo->usri4_flags & UF_DONT_EXPIRE_PASSWD) || pUserModals->usrmod0_max_passwd_age == TIMEQ_FOREVER)
|
2019-04-08 20:48:06 +00:00
|
|
|
PrintMessageString(4305);
|
2014-10-23 18:36:11 +00:00
|
|
|
else
|
2014-10-28 21:57:41 +00:00
|
|
|
PrintDateTime(dwLastSet + pUserModals->usrmod0_max_passwd_age);
|
2016-10-07 22:50:32 +00:00
|
|
|
ConPuts(StdOut, L"\n");
|
2014-10-28 21:57:41 +00:00
|
|
|
|
2019-04-06 13:32:00 +00:00
|
|
|
PrintPaddedMessageString(4423, nPaddedLength);
|
2014-10-28 21:57:41 +00:00
|
|
|
PrintDateTime(dwLastSet + pUserModals->usrmod0_min_passwd_age);
|
2017-10-29 20:38:05 +00:00
|
|
|
ConPuts(StdOut, L"\n");
|
2014-10-23 18:36:11 +00:00
|
|
|
|
2019-04-06 13:32:00 +00:00
|
|
|
PrintPaddedMessageString(4437, nPaddedLength);
|
2019-04-08 20:48:06 +00:00
|
|
|
PrintMessageString((pUserInfo->usri4_flags & UF_PASSWD_NOTREQD) ? 4301 : 4300);
|
2016-10-07 22:50:32 +00:00
|
|
|
ConPuts(StdOut, L"\n");
|
2014-11-08 21:44:32 +00:00
|
|
|
|
2019-04-06 13:32:00 +00:00
|
|
|
PrintPaddedMessageString(4438, nPaddedLength);
|
2019-04-08 20:48:06 +00:00
|
|
|
PrintMessageString((pUserInfo->usri4_flags & UF_PASSWD_CANT_CHANGE) ? 4301 : 4300);
|
2016-10-07 22:50:32 +00:00
|
|
|
ConPuts(StdOut, L"\n\n");
|
2014-10-25 21:27:05 +00:00
|
|
|
|
2019-04-06 13:32:00 +00:00
|
|
|
PrintPaddedMessageString(4424, nPaddedLength);
|
2014-11-09 13:39:20 +00:00
|
|
|
if (pUserInfo->usri4_workstations == NULL || wcslen(pUserInfo->usri4_workstations) == 0)
|
2019-04-08 20:48:06 +00:00
|
|
|
PrintMessageString(4302);
|
2014-11-09 13:39:20 +00:00
|
|
|
else
|
2016-10-07 22:50:32 +00:00
|
|
|
ConPrintf(StdOut, L"%s", pUserInfo->usri4_workstations);
|
|
|
|
ConPuts(StdOut, L"\n");
|
2014-11-08 21:44:32 +00:00
|
|
|
|
2019-04-06 13:32:00 +00:00
|
|
|
PrintPaddedMessageString(4429, nPaddedLength);
|
2016-10-07 22:50:32 +00:00
|
|
|
ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_script_path);
|
2014-11-08 21:44:32 +00:00
|
|
|
|
2019-04-06 13:32:00 +00:00
|
|
|
PrintPaddedMessageString(4439, nPaddedLength);
|
2016-10-07 22:50:32 +00:00
|
|
|
ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_profile);
|
2014-11-08 21:44:32 +00:00
|
|
|
|
2019-04-06 13:32:00 +00:00
|
|
|
PrintPaddedMessageString(4436, nPaddedLength);
|
2016-10-07 22:50:32 +00:00
|
|
|
ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_home_dir);
|
2014-11-08 21:44:32 +00:00
|
|
|
|
2019-04-06 13:32:00 +00:00
|
|
|
PrintPaddedMessageString(4430, nPaddedLength);
|
2014-10-23 18:36:11 +00:00
|
|
|
if (pUserInfo->usri4_last_logon == 0)
|
2019-04-08 20:48:06 +00:00
|
|
|
PrintMessageString(4305);
|
2014-10-23 18:36:11 +00:00
|
|
|
else
|
|
|
|
PrintDateTime(pUserInfo->usri4_last_logon);
|
2016-10-07 22:50:32 +00:00
|
|
|
ConPuts(StdOut, L"\n\n");
|
2014-11-08 21:44:32 +00:00
|
|
|
|
2019-04-06 13:32:00 +00:00
|
|
|
PrintPaddedMessageString(4432, nPaddedLength);
|
2014-11-01 19:24:44 +00:00
|
|
|
if (pUserInfo->usri4_logon_hours == NULL)
|
2019-05-18 09:26:02 +00:00
|
|
|
{
|
2019-04-08 20:48:06 +00:00
|
|
|
PrintMessageString(4302);
|
2019-05-18 09:26:02 +00:00
|
|
|
ConPuts(StdOut, L"\n");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PrintLogonHours(pUserInfo->usri4_units_per_week,
|
|
|
|
pUserInfo->usri4_logon_hours,
|
|
|
|
nPaddedLength);
|
|
|
|
}
|
2014-11-08 21:44:32 +00:00
|
|
|
|
2016-10-07 22:50:32 +00:00
|
|
|
ConPuts(StdOut, L"\n");
|
2019-04-06 13:32:00 +00:00
|
|
|
PrintPaddedMessageString(4427, nPaddedLength);
|
2014-11-01 19:24:44 +00:00
|
|
|
if (dwLocalGroupTotal != 0 && pLocalGroupInfo != NULL)
|
|
|
|
{
|
|
|
|
for (i = 0; i < dwLocalGroupTotal; i++)
|
|
|
|
{
|
|
|
|
if (i != 0)
|
2014-11-16 10:34:49 +00:00
|
|
|
PrintPadding(L' ', nPaddedLength);
|
2016-10-07 22:50:32 +00:00
|
|
|
ConPrintf(StdOut, L"*%s\n", pLocalGroupInfo[i].lgrui0_name);
|
2014-11-01 19:24:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-10-07 22:50:32 +00:00
|
|
|
ConPuts(StdOut, L"\n");
|
2014-11-01 19:24:44 +00:00
|
|
|
}
|
|
|
|
|
2019-04-06 13:32:00 +00:00
|
|
|
PrintPaddedMessageString(4431, nPaddedLength);
|
2014-11-01 19:24:44 +00:00
|
|
|
if (dwGroupTotal != 0 && pGroupInfo != NULL)
|
|
|
|
{
|
|
|
|
for (i = 0; i < dwGroupTotal; i++)
|
|
|
|
{
|
|
|
|
if (i != 0)
|
2014-11-16 10:34:49 +00:00
|
|
|
PrintPadding(L' ', nPaddedLength);
|
2016-10-07 22:50:32 +00:00
|
|
|
ConPrintf(StdOut, L"*%s\n", pGroupInfo[i].grui0_name);
|
2014-11-01 19:24:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-10-07 22:50:32 +00:00
|
|
|
ConPuts(StdOut, L"\n");
|
2014-11-01 19:24:44 +00:00
|
|
|
}
|
2014-10-25 21:27:05 +00:00
|
|
|
|
|
|
|
done:
|
2014-11-01 19:24:44 +00:00
|
|
|
if (pGroupInfo != NULL)
|
|
|
|
NetApiBufferFree(pGroupInfo);
|
|
|
|
|
|
|
|
if (pLocalGroupInfo != NULL)
|
|
|
|
NetApiBufferFree(pLocalGroupInfo);
|
|
|
|
|
2014-10-25 21:27:05 +00:00
|
|
|
if (pUserModals != NULL)
|
|
|
|
NetApiBufferFree(pUserModals);
|
2014-10-23 18:36:11 +00:00
|
|
|
|
|
|
|
if (pUserInfo != NULL)
|
|
|
|
NetApiBufferFree(pUserInfo);
|
|
|
|
|
|
|
|
return NERR_Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-11-08 14:35:27 +00:00
|
|
|
static
|
|
|
|
VOID
|
|
|
|
ReadPassword(
|
|
|
|
LPWSTR *lpPassword,
|
|
|
|
LPBOOL lpAllocated)
|
|
|
|
{
|
|
|
|
WCHAR szPassword1[PWLEN + 1];
|
|
|
|
WCHAR szPassword2[PWLEN + 1];
|
|
|
|
LPWSTR ptr;
|
|
|
|
|
|
|
|
*lpAllocated = FALSE;
|
|
|
|
|
2014-11-08 21:44:32 +00:00
|
|
|
while (TRUE)
|
|
|
|
{
|
2019-04-07 07:21:34 +00:00
|
|
|
PrintMessageString(4358);
|
2014-11-08 21:44:32 +00:00
|
|
|
ReadFromConsole(szPassword1, PWLEN + 1, FALSE);
|
2016-10-07 22:50:32 +00:00
|
|
|
ConPuts(StdOut, L"\n");
|
2014-11-08 14:35:27 +00:00
|
|
|
|
2019-04-07 07:21:34 +00:00
|
|
|
PrintMessageString(4361);
|
2014-11-08 21:44:32 +00:00
|
|
|
ReadFromConsole(szPassword2, PWLEN + 1, FALSE);
|
2016-10-07 22:50:32 +00:00
|
|
|
ConPuts(StdOut, L"\n");
|
2014-11-08 14:35:27 +00:00
|
|
|
|
2014-11-08 21:44:32 +00:00
|
|
|
if (wcslen(szPassword1) == wcslen(szPassword2) &&
|
|
|
|
wcscmp(szPassword1, szPassword2) == 0)
|
2014-11-08 14:35:27 +00:00
|
|
|
{
|
2014-11-08 21:44:32 +00:00
|
|
|
ptr = HeapAlloc(GetProcessHeap(),
|
|
|
|
0,
|
|
|
|
(wcslen(szPassword1) + 1) * sizeof(WCHAR));
|
|
|
|
if (ptr != NULL)
|
|
|
|
{
|
|
|
|
wcscpy(ptr, szPassword1);
|
|
|
|
*lpPassword = ptr;
|
|
|
|
*lpAllocated = TRUE;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-10-07 22:50:32 +00:00
|
|
|
ConPuts(StdOut, L"\n");
|
2019-04-07 07:21:34 +00:00
|
|
|
PrintMessageString(3728);
|
2014-11-08 21:44:32 +00:00
|
|
|
*lpPassword = NULL;
|
2014-11-08 14:35:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-07-07 20:06:08 +00:00
|
|
|
static
|
|
|
|
VOID
|
|
|
|
GenerateRandomPassword(
|
|
|
|
LPWSTR *lpPassword,
|
|
|
|
LPBOOL lpAllocated)
|
|
|
|
{
|
|
|
|
LPWSTR pPassword = NULL;
|
|
|
|
INT nCharsLen, i, nLength = 8;
|
|
|
|
|
|
|
|
srand(GetTickCount());
|
|
|
|
|
|
|
|
pPassword = HeapAlloc(GetProcessHeap(),
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
(nLength + 1) * sizeof(WCHAR));
|
|
|
|
if (pPassword == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nCharsLen = wcslen(szPasswordChars);
|
|
|
|
|
|
|
|
for (i = 0; i < nLength; i++)
|
|
|
|
{
|
|
|
|
pPassword[i] = szPasswordChars[rand() % nCharsLen];
|
|
|
|
}
|
|
|
|
|
|
|
|
*lpPassword = pPassword;
|
|
|
|
*lpAllocated = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-07-21 20:13:49 +00:00
|
|
|
static
|
|
|
|
NET_API_STATUS
|
|
|
|
BuildWorkstationsList(
|
|
|
|
_Out_ PWSTR *pWorkstationsList,
|
|
|
|
_In_ PWSTR pRaw)
|
|
|
|
{
|
|
|
|
BOOL isLastSep, isSep;
|
|
|
|
INT i, j;
|
|
|
|
WCHAR c;
|
|
|
|
INT nLength = 0;
|
|
|
|
INT nArgs = 0;
|
|
|
|
INT nRawLength;
|
|
|
|
PWSTR pList;
|
|
|
|
|
|
|
|
/* Check for invalid characters in the raw string */
|
|
|
|
if (wcspbrk(pRaw, L"/[]=?\\+:.") != NULL)
|
|
|
|
return 3952;
|
|
|
|
|
|
|
|
/* Count the number of workstations in the list and
|
|
|
|
* the required buffer size */
|
|
|
|
isLastSep = FALSE;
|
|
|
|
isSep = FALSE;
|
|
|
|
nRawLength = wcslen(pRaw);
|
|
|
|
for (i = 0; i < nRawLength; i++)
|
|
|
|
{
|
|
|
|
c = pRaw[i];
|
|
|
|
if (c == L',' || c == L';')
|
|
|
|
isSep = TRUE;
|
|
|
|
|
|
|
|
if (isSep == TRUE)
|
|
|
|
{
|
|
|
|
if ((isLastSep == FALSE) && (i != 0) && (i != nRawLength - 1))
|
|
|
|
nLength++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nLength++;
|
|
|
|
|
|
|
|
if (isLastSep == TRUE || (isLastSep == FALSE && i == 0))
|
|
|
|
nArgs++;
|
|
|
|
}
|
|
|
|
|
|
|
|
isLastSep = isSep;
|
|
|
|
isSep = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
nLength++;
|
|
|
|
|
|
|
|
/* Leave, if there are no workstations in the list */
|
|
|
|
if (nArgs == 0)
|
|
|
|
{
|
|
|
|
pWorkstationsList = NULL;
|
|
|
|
return NERR_Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Fail if there are more than eight workstations in the list */
|
|
|
|
if (nArgs > 8)
|
|
|
|
return 3951;
|
|
|
|
|
|
|
|
/* Allocate the buffer for the clean workstation list */
|
|
|
|
pList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nLength * sizeof(WCHAR));
|
|
|
|
if (pList == NULL)
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
|
|
|
|
/* Build the clean workstation list */
|
|
|
|
isLastSep = FALSE;
|
|
|
|
isSep = FALSE;
|
|
|
|
nRawLength = wcslen(pRaw);
|
|
|
|
for (i = 0, j = 0; i < nRawLength; i++)
|
|
|
|
{
|
|
|
|
c = pRaw[i];
|
|
|
|
if (c == L',' || c == L';')
|
|
|
|
isSep = TRUE;
|
|
|
|
|
|
|
|
if (isSep == TRUE)
|
|
|
|
{
|
|
|
|
if ((isLastSep == FALSE) && (i != 0) && (i != nRawLength - 1))
|
|
|
|
{
|
|
|
|
pList[j] = L',';
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pList[j] = c;
|
|
|
|
j++;
|
|
|
|
|
|
|
|
if (isLastSep == TRUE || (isLastSep == FALSE && i == 0))
|
|
|
|
nArgs++;
|
|
|
|
}
|
|
|
|
|
|
|
|
isLastSep = isSep;
|
|
|
|
isSep = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
*pWorkstationsList = pList;
|
|
|
|
|
|
|
|
return NERR_Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-08-25 22:13:14 +00:00
|
|
|
static
|
|
|
|
BOOL
|
|
|
|
ReadNumber(
|
|
|
|
PWSTR *s,
|
|
|
|
PWORD pwValue)
|
|
|
|
{
|
|
|
|
if (!iswdigit(**s))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
while (iswdigit(**s))
|
|
|
|
{
|
|
|
|
*pwValue = *pwValue * 10 + **s - L'0';
|
|
|
|
(*s)++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static
|
|
|
|
BOOL
|
|
|
|
ReadSeparator(
|
|
|
|
PWSTR *s)
|
|
|
|
{
|
|
|
|
if (**s == L'/' || **s == L'.')
|
|
|
|
{
|
|
|
|
(*s)++;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static
|
|
|
|
BOOL
|
|
|
|
ParseDate(
|
|
|
|
PWSTR s,
|
|
|
|
PULONG pSeconds)
|
|
|
|
{
|
|
|
|
SYSTEMTIME SystemTime = {0};
|
|
|
|
FILETIME LocalFileTime, FileTime;
|
|
|
|
LARGE_INTEGER Time;
|
|
|
|
INT nDateFormat = 0;
|
|
|
|
PWSTR p = s;
|
|
|
|
|
|
|
|
if (!*s)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
GetLocaleInfoW(LOCALE_USER_DEFAULT,
|
|
|
|
LOCALE_IDATE,
|
|
|
|
(PWSTR)&nDateFormat,
|
|
|
|
sizeof(INT));
|
|
|
|
|
|
|
|
switch (nDateFormat)
|
|
|
|
{
|
|
|
|
case 0: /* mmddyy */
|
|
|
|
default:
|
|
|
|
if (!ReadNumber(&p, &SystemTime.wMonth))
|
|
|
|
return FALSE;
|
|
|
|
if (!ReadSeparator(&p))
|
|
|
|
return FALSE;
|
|
|
|
if (!ReadNumber(&p, &SystemTime.wDay))
|
|
|
|
return FALSE;
|
|
|
|
if (!ReadSeparator(&p))
|
|
|
|
return FALSE;
|
|
|
|
if (!ReadNumber(&p, &SystemTime.wYear))
|
|
|
|
return FALSE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1: /* ddmmyy */
|
|
|
|
if (!ReadNumber(&p, &SystemTime.wDay))
|
|
|
|
return FALSE;
|
|
|
|
if (!ReadSeparator(&p))
|
|
|
|
return FALSE;
|
|
|
|
if (!ReadNumber(&p, &SystemTime.wMonth))
|
|
|
|
return FALSE;
|
|
|
|
if (!ReadSeparator(&p))
|
|
|
|
return FALSE;
|
|
|
|
if (!ReadNumber(&p, &SystemTime.wYear))
|
|
|
|
return FALSE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2: /* yymmdd */
|
|
|
|
if (!ReadNumber(&p, &SystemTime.wYear))
|
|
|
|
return FALSE;
|
|
|
|
if (!ReadSeparator(&p))
|
|
|
|
return FALSE;
|
|
|
|
if (!ReadNumber(&p, &SystemTime.wMonth))
|
|
|
|
return FALSE;
|
|
|
|
if (!ReadSeparator(&p))
|
|
|
|
return FALSE;
|
|
|
|
if (!ReadNumber(&p, &SystemTime.wDay))
|
|
|
|
return FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if only entered two digits: */
|
|
|
|
/* assume 2000's if value less than 80 */
|
|
|
|
/* assume 1900's if value greater or equal 80 */
|
|
|
|
if (SystemTime.wYear <= 99)
|
|
|
|
{
|
|
|
|
if (SystemTime.wYear >= 80)
|
|
|
|
SystemTime.wYear += 1900;
|
|
|
|
else
|
|
|
|
SystemTime.wYear += 2000;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!SystemTimeToFileTime(&SystemTime, &LocalFileTime))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!LocalFileTimeToFileTime(&LocalFileTime, &FileTime))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
Time.u.LowPart = FileTime.dwLowDateTime;
|
|
|
|
Time.u.HighPart = FileTime.dwHighDateTime;
|
|
|
|
|
|
|
|
if (!RtlTimeToSecondsSince1970(&Time, pSeconds))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-23 18:36:11 +00:00
|
|
|
INT
|
|
|
|
cmdUser(
|
|
|
|
INT argc,
|
|
|
|
WCHAR **argv)
|
|
|
|
{
|
|
|
|
INT i, j;
|
|
|
|
INT result = 0;
|
|
|
|
BOOL bAdd = FALSE;
|
|
|
|
BOOL bDelete = FALSE;
|
|
|
|
#if 0
|
|
|
|
BOOL bDomain = FALSE;
|
|
|
|
#endif
|
2018-07-07 20:06:08 +00:00
|
|
|
BOOL bRandomPassword = FALSE;
|
2014-10-23 18:36:11 +00:00
|
|
|
LPWSTR lpUserName = NULL;
|
|
|
|
LPWSTR lpPassword = NULL;
|
|
|
|
PUSER_INFO_4 pUserInfo = NULL;
|
|
|
|
USER_INFO_4 UserInfo;
|
2018-07-21 20:13:49 +00:00
|
|
|
LPWSTR pWorkstations = NULL;
|
2014-10-28 21:57:41 +00:00
|
|
|
LPWSTR p;
|
2014-11-02 09:56:18 +00:00
|
|
|
LPWSTR endptr;
|
|
|
|
DWORD value;
|
2014-11-08 14:35:27 +00:00
|
|
|
BOOL bPasswordAllocated = FALSE;
|
2014-10-23 18:36:11 +00:00
|
|
|
NET_API_STATUS Status;
|
|
|
|
|
|
|
|
i = 2;
|
2019-03-09 23:30:27 +00:00
|
|
|
if ((i < argc) && (argv[i][0] != L'/'))
|
2014-10-23 18:36:11 +00:00
|
|
|
{
|
|
|
|
lpUserName = argv[i];
|
2016-10-07 22:50:32 +00:00
|
|
|
// ConPrintf(StdOut, L"User: %s\n", lpUserName);
|
2014-10-23 18:36:11 +00:00
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
2019-03-09 23:30:27 +00:00
|
|
|
if ((i < argc) && (argv[i][0] != L'/'))
|
2014-10-23 18:36:11 +00:00
|
|
|
{
|
|
|
|
lpPassword = argv[i];
|
2016-10-07 22:50:32 +00:00
|
|
|
// ConPrintf(StdOut, L"Password: %s\n", lpPassword);
|
2014-10-23 18:36:11 +00:00
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (j = i; j < argc; j++)
|
|
|
|
{
|
|
|
|
if (_wcsicmp(argv[j], L"/help") == 0)
|
|
|
|
{
|
2018-12-24 10:48:23 +00:00
|
|
|
PrintNetMessage(MSG_USER_HELP);
|
2014-10-23 18:36:11 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else if (_wcsicmp(argv[j], L"/add") == 0)
|
|
|
|
{
|
|
|
|
bAdd = TRUE;
|
|
|
|
}
|
|
|
|
else if (_wcsicmp(argv[j], L"/delete") == 0)
|
|
|
|
{
|
|
|
|
bDelete = TRUE;
|
|
|
|
}
|
|
|
|
else if (_wcsicmp(argv[j], L"/domain") == 0)
|
|
|
|
{
|
2019-04-09 19:44:03 +00:00
|
|
|
ConPuts(StdErr, L"The /DOMAIN option is not supported yet.\n");
|
2014-10-23 18:36:11 +00:00
|
|
|
#if 0
|
|
|
|
bDomain = TRUE;
|
|
|
|
#endif
|
|
|
|
}
|
2018-07-07 20:06:08 +00:00
|
|
|
else if (_wcsicmp(argv[j], L"/random") == 0)
|
|
|
|
{
|
|
|
|
bRandomPassword = TRUE;
|
|
|
|
GenerateRandomPassword(&lpPassword,
|
|
|
|
&bPasswordAllocated);
|
|
|
|
}
|
2014-10-23 18:36:11 +00:00
|
|
|
}
|
|
|
|
|
2018-12-24 10:48:23 +00:00
|
|
|
if (lpUserName == NULL && lpPassword == NULL)
|
|
|
|
{
|
|
|
|
Status = EnumerateUsers();
|
|
|
|
ConPrintf(StdOut, L"Status: %lu\n", Status);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else if (lpUserName != NULL && lpPassword == NULL)
|
|
|
|
{
|
|
|
|
Status = DisplayUser(lpUserName);
|
|
|
|
ConPrintf(StdOut, L"Status: %lu\n", Status);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-10-23 18:36:11 +00:00
|
|
|
if (bAdd && bDelete)
|
|
|
|
{
|
|
|
|
result = 1;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2014-11-08 14:35:27 +00:00
|
|
|
/* Interactive password input */
|
|
|
|
if (lpPassword != NULL && wcscmp(lpPassword, L"*") == 0)
|
|
|
|
{
|
|
|
|
ReadPassword(&lpPassword,
|
|
|
|
&bPasswordAllocated);
|
|
|
|
}
|
|
|
|
|
2014-10-23 18:36:11 +00:00
|
|
|
if (!bAdd && !bDelete)
|
|
|
|
{
|
|
|
|
/* Modify the user */
|
|
|
|
Status = NetUserGetInfo(NULL,
|
|
|
|
lpUserName,
|
|
|
|
4,
|
|
|
|
(LPBYTE*)&pUserInfo);
|
2014-11-01 12:32:01 +00:00
|
|
|
if (Status != NERR_Success)
|
|
|
|
{
|
2016-10-07 22:50:32 +00:00
|
|
|
ConPrintf(StdOut, L"Status: %lu\n", Status);
|
2014-11-01 12:32:01 +00:00
|
|
|
result = 1;
|
|
|
|
goto done;
|
|
|
|
}
|
2014-10-23 18:36:11 +00:00
|
|
|
}
|
|
|
|
else if (bAdd && !bDelete)
|
|
|
|
{
|
|
|
|
/* Add the user */
|
|
|
|
ZeroMemory(&UserInfo, sizeof(USER_INFO_4));
|
|
|
|
|
|
|
|
UserInfo.usri4_name = lpUserName;
|
|
|
|
UserInfo.usri4_password = lpPassword;
|
|
|
|
UserInfo.usri4_flags = UF_SCRIPT | UF_NORMAL_ACCOUNT;
|
2018-08-26 18:26:34 +00:00
|
|
|
UserInfo.usri4_acct_expires = TIMEQ_FOREVER;
|
2018-08-29 20:03:53 +00:00
|
|
|
UserInfo.usri4_primary_group_id = DOMAIN_GROUP_RID_USERS;
|
2014-10-23 18:36:11 +00:00
|
|
|
|
|
|
|
pUserInfo = &UserInfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (j = i; j < argc; j++)
|
|
|
|
{
|
|
|
|
if (_wcsnicmp(argv[j], L"/active:", 8) == 0)
|
|
|
|
{
|
2014-10-28 21:57:41 +00:00
|
|
|
p = &argv[i][8];
|
|
|
|
if (_wcsicmp(p, L"yes") == 0)
|
|
|
|
{
|
2014-11-02 09:56:18 +00:00
|
|
|
pUserInfo->usri4_flags &= ~UF_ACCOUNTDISABLE;
|
2014-10-28 21:57:41 +00:00
|
|
|
}
|
|
|
|
else if (_wcsicmp(p, L"no") == 0)
|
|
|
|
{
|
2014-11-02 09:56:18 +00:00
|
|
|
pUserInfo->usri4_flags |= UF_ACCOUNTDISABLE;
|
2014-10-28 21:57:41 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-04-09 19:44:03 +00:00
|
|
|
PrintMessageStringV(3952, L"/ACTIVE");
|
2014-10-28 21:57:41 +00:00
|
|
|
result = 1;
|
|
|
|
goto done;
|
|
|
|
}
|
2014-10-23 18:36:11 +00:00
|
|
|
}
|
|
|
|
else if (_wcsnicmp(argv[j], L"/comment:", 9) == 0)
|
|
|
|
{
|
|
|
|
pUserInfo->usri4_comment = &argv[j][9];
|
|
|
|
}
|
|
|
|
else if (_wcsnicmp(argv[j], L"/countrycode:", 13) == 0)
|
|
|
|
{
|
2014-11-02 09:56:18 +00:00
|
|
|
p = &argv[i][13];
|
|
|
|
value = wcstoul(p, &endptr, 10);
|
|
|
|
if (*endptr != 0)
|
|
|
|
{
|
2019-04-09 19:44:03 +00:00
|
|
|
PrintMessageStringV(3952, L"/COUNTRYCODE");
|
2014-11-02 09:56:18 +00:00
|
|
|
result = 1;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2019-03-10 21:00:41 +00:00
|
|
|
/* Verify the country code */
|
|
|
|
if (GetCountryFromCountryCode(value, 0, NULL))
|
|
|
|
pUserInfo->usri4_country_code = value;
|
2014-10-23 18:36:11 +00:00
|
|
|
}
|
|
|
|
else if (_wcsnicmp(argv[j], L"/expires:", 9) == 0)
|
|
|
|
{
|
2014-11-08 14:35:27 +00:00
|
|
|
p = &argv[i][9];
|
|
|
|
if (_wcsicmp(p, L"never") == 0)
|
|
|
|
{
|
|
|
|
pUserInfo->usri4_acct_expires = TIMEQ_FOREVER;
|
|
|
|
}
|
2018-08-25 22:13:14 +00:00
|
|
|
else if (!ParseDate(p, &pUserInfo->usri4_acct_expires))
|
2014-11-08 14:35:27 +00:00
|
|
|
{
|
2019-04-09 19:44:03 +00:00
|
|
|
PrintMessageStringV(3952, L"/EXPIRES");
|
2018-08-25 22:13:14 +00:00
|
|
|
result = 1;
|
|
|
|
goto done;
|
2014-11-08 14:35:27 +00:00
|
|
|
}
|
2014-10-23 18:36:11 +00:00
|
|
|
}
|
|
|
|
else if (_wcsnicmp(argv[j], L"/fullname:", 10) == 0)
|
|
|
|
{
|
|
|
|
pUserInfo->usri4_full_name = &argv[j][10];
|
|
|
|
}
|
|
|
|
else if (_wcsnicmp(argv[j], L"/homedir:", 9) == 0)
|
|
|
|
{
|
|
|
|
pUserInfo->usri4_home_dir = &argv[j][9];
|
|
|
|
}
|
|
|
|
else if (_wcsnicmp(argv[j], L"/passwordchg:", 13) == 0)
|
|
|
|
{
|
2014-11-02 09:56:18 +00:00
|
|
|
p = &argv[i][13];
|
|
|
|
if (_wcsicmp(p, L"yes") == 0)
|
|
|
|
{
|
|
|
|
pUserInfo->usri4_flags &= ~UF_PASSWD_CANT_CHANGE;
|
|
|
|
}
|
|
|
|
else if (_wcsicmp(p, L"no") == 0)
|
|
|
|
{
|
|
|
|
pUserInfo->usri4_flags |= UF_PASSWD_CANT_CHANGE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-04-09 19:44:03 +00:00
|
|
|
PrintMessageStringV(3952, L"/PASSWORDCHG");
|
2014-11-02 09:56:18 +00:00
|
|
|
result = 1;
|
|
|
|
goto done;
|
|
|
|
}
|
2014-10-23 18:36:11 +00:00
|
|
|
}
|
|
|
|
else if (_wcsnicmp(argv[j], L"/passwordreq:", 13) == 0)
|
|
|
|
{
|
2014-11-02 09:56:18 +00:00
|
|
|
p = &argv[i][13];
|
|
|
|
if (_wcsicmp(p, L"yes") == 0)
|
|
|
|
{
|
|
|
|
pUserInfo->usri4_flags &= ~UF_PASSWD_NOTREQD;
|
|
|
|
}
|
|
|
|
else if (_wcsicmp(p, L"no") == 0)
|
|
|
|
{
|
|
|
|
pUserInfo->usri4_flags |= UF_PASSWD_NOTREQD;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-04-09 19:44:03 +00:00
|
|
|
PrintMessageStringV(3952, L"/PASSWORDREQ");
|
2014-11-02 09:56:18 +00:00
|
|
|
result = 1;
|
|
|
|
goto done;
|
|
|
|
}
|
2014-10-23 18:36:11 +00:00
|
|
|
}
|
|
|
|
else if (_wcsnicmp(argv[j], L"/profilepath:", 13) == 0)
|
|
|
|
{
|
|
|
|
pUserInfo->usri4_profile = &argv[j][13];
|
|
|
|
}
|
|
|
|
else if (_wcsnicmp(argv[j], L"/scriptpath:", 12) == 0)
|
|
|
|
{
|
|
|
|
pUserInfo->usri4_script_path = &argv[j][12];
|
|
|
|
}
|
|
|
|
else if (_wcsnicmp(argv[j], L"/times:", 7) == 0)
|
|
|
|
{
|
2014-11-08 14:35:27 +00:00
|
|
|
/* FIXME */
|
2019-04-09 19:44:03 +00:00
|
|
|
ConPuts(StdErr, L"The /TIMES option is not supported yet.\n");
|
2014-10-23 18:36:11 +00:00
|
|
|
}
|
|
|
|
else if (_wcsnicmp(argv[j], L"/usercomment:", 13) == 0)
|
|
|
|
{
|
|
|
|
pUserInfo->usri4_usr_comment = &argv[j][13];
|
|
|
|
}
|
|
|
|
else if (_wcsnicmp(argv[j], L"/workstations:", 14) == 0)
|
|
|
|
{
|
2018-07-21 20:13:49 +00:00
|
|
|
p = &argv[i][14];
|
|
|
|
if (wcscmp(p, L"*") == 0 || wcscmp(p, L"") == 0)
|
|
|
|
{
|
|
|
|
pUserInfo->usri4_workstations = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Status = BuildWorkstationsList(&pWorkstations, p);
|
|
|
|
if (Status == NERR_Success)
|
|
|
|
{
|
|
|
|
pUserInfo->usri4_workstations = pWorkstations;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ConPrintf(StdOut, L"Status %lu\n\n", Status);
|
|
|
|
result = 1;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
2014-10-23 18:36:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!bAdd && !bDelete)
|
|
|
|
{
|
|
|
|
/* Modify the user */
|
|
|
|
Status = NetUserSetInfo(NULL,
|
|
|
|
lpUserName,
|
|
|
|
4,
|
|
|
|
(LPBYTE)pUserInfo,
|
|
|
|
NULL);
|
2016-10-07 22:50:32 +00:00
|
|
|
ConPrintf(StdOut, L"Status: %lu\n", Status);
|
2014-10-23 18:36:11 +00:00
|
|
|
}
|
|
|
|
else if (bAdd && !bDelete)
|
|
|
|
{
|
|
|
|
/* Add the user */
|
|
|
|
Status = NetUserAdd(NULL,
|
|
|
|
4,
|
|
|
|
(LPBYTE)pUserInfo,
|
|
|
|
NULL);
|
2016-10-07 22:50:32 +00:00
|
|
|
ConPrintf(StdOut, L"Status: %lu\n", Status);
|
2014-10-23 18:36:11 +00:00
|
|
|
}
|
|
|
|
else if (!bAdd && bDelete)
|
|
|
|
{
|
|
|
|
/* Delete the user */
|
|
|
|
Status = NetUserDel(NULL,
|
|
|
|
lpUserName);
|
2016-10-07 22:50:32 +00:00
|
|
|
ConPrintf(StdOut, L"Status: %lu\n", Status);
|
2014-10-23 18:36:11 +00:00
|
|
|
}
|
|
|
|
|
2018-07-07 20:06:08 +00:00
|
|
|
if (Status == NERR_Success &&
|
|
|
|
lpPassword != NULL &&
|
|
|
|
bRandomPassword == TRUE)
|
|
|
|
{
|
2019-04-07 07:21:34 +00:00
|
|
|
PrintMessageStringV(3968, lpUserName, lpPassword);
|
2018-07-07 20:06:08 +00:00
|
|
|
}
|
|
|
|
|
2014-10-23 18:36:11 +00:00
|
|
|
done:
|
2018-07-21 20:13:49 +00:00
|
|
|
if (pWorkstations != NULL)
|
|
|
|
HeapFree(GetProcessHeap(), 0, pWorkstations);
|
|
|
|
|
2018-07-07 20:12:37 +00:00
|
|
|
if ((bPasswordAllocated == TRUE) && (lpPassword != NULL))
|
2014-11-08 14:35:27 +00:00
|
|
|
HeapFree(GetProcessHeap(), 0, lpPassword);
|
|
|
|
|
2014-10-23 18:36:11 +00:00
|
|
|
if (!bAdd && !bDelete && pUserInfo != NULL)
|
|
|
|
NetApiBufferFree(pUserInfo);
|
|
|
|
|
|
|
|
if (result != 0)
|
2018-04-01 10:23:15 +00:00
|
|
|
{
|
2019-04-09 19:44:03 +00:00
|
|
|
PrintMessageString(4381);
|
|
|
|
ConPuts(StdOut, L"\n");
|
2018-12-24 10:48:23 +00:00
|
|
|
PrintNetMessage(MSG_USER_SYNTAX);
|
2018-04-01 10:23:15 +00:00
|
|
|
}
|
2014-10-23 18:36:11 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* EOF */
|