1c2c66affSColin Finck /*
2c2c66affSColin Finck  * COPYRIGHT:       See COPYING in the top level directory
3c2c66affSColin Finck  * PROJECT:         ReactOS net command
4c2c66affSColin Finck  * FILE:            base/applications/network/net/cmdUser.c
5c2c66affSColin Finck  * PURPOSE:
6c2c66affSColin Finck  *
7c2c66affSColin Finck  * PROGRAMMERS:     Eric Kohl
8c2c66affSColin Finck  *                  Curtis Wilson
9c2c66affSColin Finck  */
10c2c66affSColin Finck 
11c2c66affSColin Finck #include "net.h"
12c2c66affSColin Finck 
130ca92979SEric Kohl #define SECONDS_PER_DAY (60 * 60 * 24)
140ca92979SEric Kohl #define SECONDS_PER_HOUR (60 * 60)
15ccd95b98SEric Kohl #define HOURS_PER_DAY 24
16ccd95b98SEric Kohl #define DAYS_PER_WEEK 7
170ca92979SEric Kohl 
1808d30403SEric Kohl typedef struct _COUNTY_TABLE
1908d30403SEric Kohl {
2008d30403SEric Kohl     DWORD dwCountryCode;
2108d30403SEric Kohl     DWORD dwMessageId;
2208d30403SEric Kohl } COUNTRY_TABLE, *PCOUNTRY_TABLE;
2308d30403SEric Kohl 
2408d30403SEric Kohl 
25b4969dc0SEric Kohl static WCHAR szPasswordChars[] = L"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@#$%_-+:";
2608d30403SEric Kohl static COUNTRY_TABLE CountryTable[] =
2708d30403SEric Kohl { {  0, 5080},   // System Default
2808d30403SEric Kohl   {  1, 5081},   // United States
2908d30403SEric Kohl   {  2, 5082},   // Canada (French)
3008d30403SEric Kohl   {  3, 5083},   // Latin America
3108d30403SEric Kohl   { 31, 5084},   // Netherlands
3208d30403SEric Kohl   { 32, 5085},   // Belgium
3308d30403SEric Kohl   { 33, 5086},   // France
3408d30403SEric Kohl   { 34, 5090},   // Spain
3508d30403SEric Kohl   { 39, 5087},   // Italy
3608d30403SEric Kohl   { 41, 5088},   // Switzerland
3708d30403SEric Kohl   { 44, 5089},   // United Kingdom
3808d30403SEric Kohl   { 45, 5091},   // Denmark
3908d30403SEric Kohl   { 46, 5092},   // Sweden
4008d30403SEric Kohl   { 47, 5093},   // Norway
4108d30403SEric Kohl   { 49, 5094},   // Germany
4208d30403SEric Kohl   { 61, 5095},   // Australia
4308d30403SEric Kohl   { 81, 5096},   // Japan
4408d30403SEric Kohl   { 82, 5097},   // Korea
4508d30403SEric Kohl   { 86, 5098},   // China (PRC)
4608d30403SEric Kohl   { 88, 5099},   // Taiwan
4708d30403SEric Kohl   { 99, 5100},   // Asia
4808d30403SEric Kohl   {351, 5101},   // Portugal
4908d30403SEric Kohl   {358, 5102},   // Finland
5008d30403SEric Kohl   {785, 5103},   // Arabic
5108d30403SEric Kohl   {972, 5104} }; // Hebrew
5208d30403SEric Kohl 
53b4969dc0SEric Kohl 
54c2c66affSColin Finck static
55c2c66affSColin Finck int
CompareInfo(const void * a,const void * b)56506bd64eSEric Kohl CompareInfo(const void *a, const void *b)
57c2c66affSColin Finck {
58c2c66affSColin Finck     return _wcsicmp(((PUSER_INFO_0)a)->usri0_name,
59c2c66affSColin Finck                     ((PUSER_INFO_0)b)->usri0_name);
60c2c66affSColin Finck }
61c2c66affSColin Finck 
62c2c66affSColin Finck 
63c2c66affSColin Finck static
64c2c66affSColin Finck NET_API_STATUS
EnumerateUsers(VOID)65c2c66affSColin Finck EnumerateUsers(VOID)
66c2c66affSColin Finck {
67c2c66affSColin Finck     PUSER_INFO_0 pBuffer = NULL;
68c2c66affSColin Finck     PSERVER_INFO_100 pServer = NULL;
69c2c66affSColin Finck     DWORD dwRead = 0, dwTotal = 0;
70c2c66affSColin Finck     DWORD i;
716f130666STimo Kreuzer     DWORD ResumeHandle = 0;
72c2c66affSColin Finck     NET_API_STATUS Status;
73c2c66affSColin Finck 
74c2c66affSColin Finck     Status = NetServerGetInfo(NULL,
75c2c66affSColin Finck                               100,
76c2c66affSColin Finck                               (LPBYTE*)&pServer);
77c2c66affSColin Finck     if (Status != NERR_Success)
78c2c66affSColin Finck         return Status;
79c2c66affSColin Finck 
80c2c66affSColin Finck     ConPuts(StdOut, L"\n");
81050db4faSEric Kohl     PrintMessageStringV(4410, pServer->sv100_name);
82050db4faSEric Kohl     ConPuts(StdOut, L"\n");
83c2c66affSColin Finck     PrintPadding(L'-', 79);
84c2c66affSColin Finck     ConPuts(StdOut, L"\n");
85c2c66affSColin Finck 
86c2c66affSColin Finck     NetApiBufferFree(pServer);
87c2c66affSColin Finck 
88c2c66affSColin Finck     do
89c2c66affSColin Finck     {
90c2c66affSColin Finck         Status = NetUserEnum(NULL,
91c2c66affSColin Finck                              0,
92c2c66affSColin Finck                              0,
93c2c66affSColin Finck                              (LPBYTE*)&pBuffer,
94c2c66affSColin Finck                              MAX_PREFERRED_LENGTH,
95c2c66affSColin Finck                              &dwRead,
96c2c66affSColin Finck                              &dwTotal,
97c2c66affSColin Finck                              &ResumeHandle);
98c2c66affSColin Finck         if ((Status != NERR_Success) && (Status != ERROR_MORE_DATA))
99c2c66affSColin Finck             return Status;
100c2c66affSColin Finck 
101c2c66affSColin Finck         qsort(pBuffer,
102c2c66affSColin Finck               dwRead,
103c2c66affSColin Finck               sizeof(PUSER_INFO_0),
104506bd64eSEric Kohl               CompareInfo);
105c2c66affSColin Finck 
106c2c66affSColin Finck         for (i = 0; i < dwRead; i++)
107c2c66affSColin Finck         {
108c2c66affSColin Finck             if (pBuffer[i].usri0_name)
109c2c66affSColin Finck                 ConPrintf(StdOut, L"%s\n", pBuffer[i].usri0_name);
110c2c66affSColin Finck         }
111c2c66affSColin Finck 
112c2c66affSColin Finck         NetApiBufferFree(pBuffer);
113c2c66affSColin Finck         pBuffer = NULL;
114c2c66affSColin Finck     }
115c2c66affSColin Finck     while (Status == ERROR_MORE_DATA);
116c2c66affSColin Finck 
117c2c66affSColin Finck     return NERR_Success;
118c2c66affSColin Finck }
119c2c66affSColin Finck 
120c2c66affSColin Finck 
121c2c66affSColin Finck static
122c2c66affSColin Finck VOID
PrintDateTime(DWORD dwSeconds)123c2c66affSColin Finck PrintDateTime(DWORD dwSeconds)
124c2c66affSColin Finck {
125c2c66affSColin Finck     LARGE_INTEGER Time;
126c2c66affSColin Finck     FILETIME FileTime;
127c2c66affSColin Finck     SYSTEMTIME SystemTime;
128c2c66affSColin Finck     WCHAR DateBuffer[80];
129c2c66affSColin Finck     WCHAR TimeBuffer[80];
130c2c66affSColin Finck 
131c2c66affSColin Finck     RtlSecondsSince1970ToTime(dwSeconds, &Time);
132c2c66affSColin Finck     FileTime.dwLowDateTime = Time.u.LowPart;
133c2c66affSColin Finck     FileTime.dwHighDateTime = Time.u.HighPart;
134c2c66affSColin Finck     FileTimeToLocalFileTime(&FileTime, &FileTime);
135c2c66affSColin Finck     FileTimeToSystemTime(&FileTime, &SystemTime);
136c2c66affSColin Finck 
137c2c66affSColin Finck     GetDateFormatW(LOCALE_USER_DEFAULT,
138c2c66affSColin Finck                    DATE_SHORTDATE,
139c2c66affSColin Finck                    &SystemTime,
140c2c66affSColin Finck                    NULL,
141c2c66affSColin Finck                    DateBuffer,
1424cf5013aSEric Kohl                    ARRAYSIZE(DateBuffer));
143c2c66affSColin Finck 
144c2c66affSColin Finck     GetTimeFormatW(LOCALE_USER_DEFAULT,
145c2c66affSColin Finck                    TIME_NOSECONDS,
146c2c66affSColin Finck                    &SystemTime,
147c2c66affSColin Finck                    NULL,
148c2c66affSColin Finck                    TimeBuffer,
1494cf5013aSEric Kohl                    ARRAYSIZE(TimeBuffer));
150c2c66affSColin Finck 
151c2c66affSColin Finck     ConPrintf(StdOut, L"%s %s", DateBuffer, TimeBuffer);
152c2c66affSColin Finck }
153c2c66affSColin Finck 
154c2c66affSColin Finck 
155c2c66affSColin Finck static
1560ca92979SEric Kohl VOID
PrintLocalTime(DWORD dwSeconds)1570ca92979SEric Kohl PrintLocalTime(DWORD dwSeconds)
1580ca92979SEric Kohl {
1590ca92979SEric Kohl     LARGE_INTEGER Time;
1600ca92979SEric Kohl     FILETIME FileTime;
1610ca92979SEric Kohl     SYSTEMTIME SystemTime;
1620ca92979SEric Kohl     WCHAR TimeBuffer[80];
1630ca92979SEric Kohl 
1640ca92979SEric Kohl     RtlSecondsSince1970ToTime(dwSeconds, &Time);
1650ca92979SEric Kohl     FileTime.dwLowDateTime = Time.u.LowPart;
1660ca92979SEric Kohl     FileTime.dwHighDateTime = Time.u.HighPart;
1670ca92979SEric Kohl     FileTimeToSystemTime(&FileTime, &SystemTime);
1680ca92979SEric Kohl 
1690ca92979SEric Kohl     GetTimeFormatW(LOCALE_USER_DEFAULT,
1700ca92979SEric Kohl                    TIME_NOSECONDS,
1710ca92979SEric Kohl                    &SystemTime,
1720ca92979SEric Kohl                    NULL,
1730ca92979SEric Kohl                    TimeBuffer,
1740ca92979SEric Kohl                    ARRAYSIZE(TimeBuffer));
1750ca92979SEric Kohl 
1760ca92979SEric Kohl     ConPrintf(StdOut, L"%s", TimeBuffer);
1770ca92979SEric Kohl }
1780ca92979SEric Kohl 
1790ca92979SEric Kohl 
1800ca92979SEric Kohl static
181c2c66affSColin Finck DWORD
GetTimeInSeconds(VOID)182c2c66affSColin Finck GetTimeInSeconds(VOID)
183c2c66affSColin Finck {
184c2c66affSColin Finck     LARGE_INTEGER Time;
185c2c66affSColin Finck     FILETIME FileTime;
186c2c66affSColin Finck     DWORD dwSeconds;
187c2c66affSColin Finck 
188c2c66affSColin Finck     GetSystemTimeAsFileTime(&FileTime);
189c2c66affSColin Finck     Time.u.LowPart = FileTime.dwLowDateTime;
190c2c66affSColin Finck     Time.u.HighPart = FileTime.dwHighDateTime;
191c2c66affSColin Finck     RtlTimeToSecondsSince1970(&Time, &dwSeconds);
192c2c66affSColin Finck 
193c2c66affSColin Finck     return dwSeconds;
194c2c66affSColin Finck }
195c2c66affSColin Finck 
196c2c66affSColin Finck 
197c2c66affSColin Finck static
19808d30403SEric Kohl BOOL
GetCountryFromCountryCode(_In_ DWORD dwCountryCode,_In_ DWORD dwCountryLength,_Out_ PWSTR szCountryBuffer)19908d30403SEric Kohl GetCountryFromCountryCode(
20008d30403SEric Kohl     _In_ DWORD dwCountryCode,
20108d30403SEric Kohl     _In_ DWORD dwCountryLength,
20208d30403SEric Kohl     _Out_ PWSTR szCountryBuffer)
20308d30403SEric Kohl {
20408d30403SEric Kohl     DWORD i;
20508d30403SEric Kohl 
20608d30403SEric Kohl     for (i = 0; i < ARRAYSIZE(CountryTable); i++)
20708d30403SEric Kohl     {
20808d30403SEric Kohl         if (CountryTable[i].dwCountryCode == dwCountryCode)
20908d30403SEric Kohl         {
21008d30403SEric Kohl             if (szCountryBuffer != NULL && dwCountryLength > 0)
21108d30403SEric Kohl             {
21208d30403SEric Kohl                 FormatMessageW(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS,
21308d30403SEric Kohl                                hModuleNetMsg,
21408d30403SEric Kohl                                CountryTable[i].dwMessageId,
21508d30403SEric Kohl                                LANG_USER_DEFAULT,
21608d30403SEric Kohl                                szCountryBuffer,
21708d30403SEric Kohl                                dwCountryLength,
21808d30403SEric Kohl                                NULL);
21908d30403SEric Kohl             }
22008d30403SEric Kohl 
22108d30403SEric Kohl             return TRUE;
22208d30403SEric Kohl         }
22308d30403SEric Kohl     }
22408d30403SEric Kohl 
22508d30403SEric Kohl     return FALSE;
22608d30403SEric Kohl }
22708d30403SEric Kohl 
22808d30403SEric Kohl 
22908d30403SEric Kohl static
2304cf5013aSEric Kohl BOOL
GetBitValue(PBYTE pBitmap,DWORD dwBitNumber)231ccd95b98SEric Kohl GetBitValue(
232ccd95b98SEric Kohl     PBYTE pBitmap,
2334cf5013aSEric Kohl     DWORD dwBitNumber)
2344cf5013aSEric Kohl {
2354cf5013aSEric Kohl     DWORD dwIndex = dwBitNumber / 8;
2364cf5013aSEric Kohl     BYTE Mask = 1 << (dwBitNumber & 7);
2374cf5013aSEric Kohl 
238ccd95b98SEric Kohl     return ((pBitmap[dwIndex] & Mask) != 0);
239ccd95b98SEric Kohl }
240ccd95b98SEric Kohl 
241ccd95b98SEric Kohl 
242ccd95b98SEric Kohl static
243ccd95b98SEric Kohl VOID
SetBitValue(PBYTE pBitmap,DWORD dwBitNumber)244ccd95b98SEric Kohl SetBitValue(
245ccd95b98SEric Kohl     PBYTE pBitmap,
246ccd95b98SEric Kohl     DWORD dwBitNumber)
247ccd95b98SEric Kohl {
248ccd95b98SEric Kohl     DWORD dwIndex = dwBitNumber / 8;
249ccd95b98SEric Kohl     BYTE Mask = 1 << (dwBitNumber & 7);
250ccd95b98SEric Kohl 
251ccd95b98SEric Kohl     pBitmap[dwIndex] |= Mask;
2524cf5013aSEric Kohl }
2534cf5013aSEric Kohl 
2544cf5013aSEric Kohl 
2554cf5013aSEric Kohl static
2564cf5013aSEric Kohl VOID
PrintLogonHours(DWORD dwUnitsPerWeek,PBYTE pLogonHours,INT nPaddedLength)2574cf5013aSEric Kohl PrintLogonHours(
2584cf5013aSEric Kohl     DWORD dwUnitsPerWeek,
2594cf5013aSEric Kohl     PBYTE pLogonHours,
2604cf5013aSEric Kohl     INT nPaddedLength)
2614cf5013aSEric Kohl {
2624cf5013aSEric Kohl     DWORD dwUnitsPerDay, dwBitNumber, dwSecondsPerUnit;
263e5b635edSEric Kohl     DWORD dwStartTime, dwEndTime, dwStartDay, dwEndDay, dwBias;
2644cf5013aSEric Kohl     BOOL bBitValue, bFirst = TRUE;
265e5b635edSEric Kohl     TIME_ZONE_INFORMATION TimeZoneInformation;
266e5b635edSEric Kohl 
267e5b635edSEric Kohl     GetTimeZoneInformation(&TimeZoneInformation);
268e5b635edSEric Kohl     dwBias = (TimeZoneInformation.Bias / 60) * SECONDS_PER_HOUR;
2694cf5013aSEric Kohl 
2704cf5013aSEric Kohl     if ((dwUnitsPerWeek == 0) ||
2714cf5013aSEric Kohl         ((dwUnitsPerWeek %7) != 0))
2724cf5013aSEric Kohl         return;
2734cf5013aSEric Kohl 
2744cf5013aSEric Kohl     dwUnitsPerDay = dwUnitsPerWeek / 7;
2754cf5013aSEric Kohl 
2764cf5013aSEric Kohl     if (((dwUnitsPerDay % 24) != 0) ||
2774cf5013aSEric Kohl         ((dwUnitsPerDay / 24) > 6))
2784cf5013aSEric Kohl         return;
2794cf5013aSEric Kohl 
2800ca92979SEric Kohl     dwSecondsPerUnit = (SECONDS_PER_DAY) / dwUnitsPerDay;
2814cf5013aSEric Kohl 
2824cf5013aSEric Kohl     for (dwBitNumber = 0; dwBitNumber < dwUnitsPerWeek; dwBitNumber++)
2834cf5013aSEric Kohl     {
284ccd95b98SEric Kohl         bBitValue = GetBitValue(pLogonHours, dwBitNumber);
2854cf5013aSEric Kohl         if (bBitValue)
2864cf5013aSEric Kohl         {
2874cf5013aSEric Kohl             dwStartTime = dwSecondsPerUnit * dwBitNumber;
2884cf5013aSEric Kohl 
2894cf5013aSEric Kohl             while (bBitValue != 0 && dwBitNumber < dwUnitsPerWeek)
2904cf5013aSEric Kohl             {
2914cf5013aSEric Kohl                 dwBitNumber++;
2924cf5013aSEric Kohl                 if (dwBitNumber < dwUnitsPerWeek)
293ccd95b98SEric Kohl                     bBitValue = GetBitValue(pLogonHours, dwBitNumber);
2944cf5013aSEric Kohl             }
2954cf5013aSEric Kohl 
2964cf5013aSEric Kohl             dwEndTime = dwSecondsPerUnit * dwBitNumber;
2974cf5013aSEric Kohl 
2984cf5013aSEric Kohl             if (!bFirst)
2994cf5013aSEric Kohl                 PrintPadding(L' ', nPaddedLength);
3004cf5013aSEric Kohl 
3010ca92979SEric Kohl             if (dwStartTime == 0 && dwEndTime == (SECONDS_PER_DAY * 7))
3024cf5013aSEric Kohl             {
3034cf5013aSEric Kohl                 PrintMessageString(4302);
3044cf5013aSEric Kohl                 ConPuts(StdOut, L"\n");
3054cf5013aSEric Kohl             }
3064cf5013aSEric Kohl             else
3074cf5013aSEric Kohl             {
3080ca92979SEric Kohl                 dwStartDay = dwStartTime / SECONDS_PER_DAY;
3090ca92979SEric Kohl                 dwEndDay = (dwEndTime / SECONDS_PER_DAY) % 7;
3100ca92979SEric Kohl 
3110ca92979SEric Kohl                 PrintMessageString(4307 + dwStartDay);
3120ca92979SEric Kohl                 ConPuts(StdOut, L" ");
313ccd95b98SEric Kohl 
314e5b635edSEric Kohl                 /* Convert from GMT to local timezone */
315e5b635edSEric Kohl                 PrintLocalTime((dwStartTime % SECONDS_PER_DAY) - dwBias);
3160ca92979SEric Kohl 
3170ca92979SEric Kohl                 ConPrintf(StdOut, L" - ");
3180ca92979SEric Kohl                 if (dwStartDay != dwEndDay)
3190ca92979SEric Kohl                 {
3200ca92979SEric Kohl                     PrintMessageString(4307 + dwEndDay);
3210ca92979SEric Kohl                     ConPuts(StdOut, L" ");
3220ca92979SEric Kohl                 }
3230ca92979SEric Kohl 
324e5b635edSEric Kohl                 /* Convert from GMT to local timezone */
325e5b635edSEric Kohl                 PrintLocalTime((dwEndTime % SECONDS_PER_DAY) - dwBias);
3260ca92979SEric Kohl                 ConPuts(StdOut, L"\n");
3274cf5013aSEric Kohl             }
3284cf5013aSEric Kohl 
3294cf5013aSEric Kohl             bFirst = FALSE;
3304cf5013aSEric Kohl         }
3314cf5013aSEric Kohl     }
33223825149SEric Kohl 
33323825149SEric Kohl     if (bFirst)
33423825149SEric Kohl     {
33523825149SEric Kohl         /* No logon hours */
33623825149SEric Kohl         PrintMessageString(4434);
33723825149SEric Kohl         ConPuts(StdOut, L"\n");
33823825149SEric Kohl     }
3394cf5013aSEric Kohl }
3404cf5013aSEric Kohl 
3414cf5013aSEric Kohl 
3424cf5013aSEric Kohl static
343c2c66affSColin Finck NET_API_STATUS
DisplayUser(LPWSTR lpUserName)344c2c66affSColin Finck DisplayUser(LPWSTR lpUserName)
345c2c66affSColin Finck {
346c2c66affSColin Finck     PUSER_MODALS_INFO_0 pUserModals = NULL;
347c2c66affSColin Finck     PUSER_INFO_4 pUserInfo = NULL;
348c2c66affSColin Finck     PLOCALGROUP_USERS_INFO_0 pLocalGroupInfo = NULL;
349c2c66affSColin Finck     PGROUP_USERS_INFO_0 pGroupInfo = NULL;
350c2c66affSColin Finck     DWORD dwLocalGroupRead, dwLocalGroupTotal;
351c2c66affSColin Finck     DWORD dwGroupRead, dwGroupTotal;
352c2c66affSColin Finck     DWORD dwLastSet;
353c2c66affSColin Finck     DWORD i;
35408d30403SEric Kohl     WCHAR szCountry[40];
355050db4faSEric Kohl     INT nPaddedLength = 36;
356c2c66affSColin Finck     NET_API_STATUS Status;
357c2c66affSColin Finck 
358c2c66affSColin Finck     /* Modify the user */
359c2c66affSColin Finck     Status = NetUserGetInfo(NULL,
360c2c66affSColin Finck                             lpUserName,
361c2c66affSColin Finck                             4,
362c2c66affSColin Finck                             (LPBYTE*)&pUserInfo);
363c2c66affSColin Finck     if (Status != NERR_Success)
364c2c66affSColin Finck         return Status;
365c2c66affSColin Finck 
366c2c66affSColin Finck     Status = NetUserModalsGet(NULL,
367c2c66affSColin Finck                               0,
368c2c66affSColin Finck                               (LPBYTE*)&pUserModals);
369c2c66affSColin Finck     if (Status != NERR_Success)
370c2c66affSColin Finck         goto done;
371c2c66affSColin Finck 
372c2c66affSColin Finck     Status = NetUserGetLocalGroups(NULL,
373c2c66affSColin Finck                                    lpUserName,
374c2c66affSColin Finck                                    0,
375c2c66affSColin Finck                                    0,
376c2c66affSColin Finck                                    (LPBYTE*)&pLocalGroupInfo,
377c2c66affSColin Finck                                    MAX_PREFERRED_LENGTH,
378c2c66affSColin Finck                                    &dwLocalGroupRead,
379c2c66affSColin Finck                                    &dwLocalGroupTotal);
380c2c66affSColin Finck     if (Status != NERR_Success)
381c2c66affSColin Finck         goto done;
382c2c66affSColin Finck 
383c2c66affSColin Finck     Status = NetUserGetGroups(NULL,
384c2c66affSColin Finck                               lpUserName,
385c2c66affSColin Finck                               0,
386c2c66affSColin Finck                               (LPBYTE*)&pGroupInfo,
387c2c66affSColin Finck                               MAX_PREFERRED_LENGTH,
388c2c66affSColin Finck                               &dwGroupRead,
389c2c66affSColin Finck                               &dwGroupTotal);
390c2c66affSColin Finck     if (Status != NERR_Success)
391c2c66affSColin Finck         goto done;
392c2c66affSColin Finck 
393050db4faSEric Kohl     PrintPaddedMessageString(4411, nPaddedLength);
394c2c66affSColin Finck     ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_name);
395c2c66affSColin Finck 
396050db4faSEric Kohl     PrintPaddedMessageString(4412, nPaddedLength);
397c2c66affSColin Finck     ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_full_name);
398c2c66affSColin Finck 
399050db4faSEric Kohl     PrintPaddedMessageString(4413, nPaddedLength);
400c2c66affSColin Finck     ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_comment);
401c2c66affSColin Finck 
402050db4faSEric Kohl     PrintPaddedMessageString(4414, nPaddedLength);
403c2c66affSColin Finck     ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_usr_comment);
404c2c66affSColin Finck 
405050db4faSEric Kohl     PrintPaddedMessageString(4416, nPaddedLength);
40608d30403SEric Kohl     GetCountryFromCountryCode(pUserInfo->usri4_country_code,
40708d30403SEric Kohl                               ARRAYSIZE(szCountry), szCountry);
40808d30403SEric Kohl     ConPrintf(StdOut, L"%03ld (%s)\n", pUserInfo->usri4_country_code, szCountry);
409c2c66affSColin Finck 
410050db4faSEric Kohl     PrintPaddedMessageString(4419, nPaddedLength);
411c2c66affSColin Finck     if (pUserInfo->usri4_flags & UF_ACCOUNTDISABLE)
41288f899e1SEric Kohl         PrintMessageString(4301);
413c2c66affSColin Finck     else if (pUserInfo->usri4_flags & UF_LOCKOUT)
414050db4faSEric Kohl         PrintMessageString(4440);
415c2c66affSColin Finck     else
41688f899e1SEric Kohl         PrintMessageString(4300);
417c2c66affSColin Finck     ConPuts(StdOut, L"\n");
418c2c66affSColin Finck 
419050db4faSEric Kohl     PrintPaddedMessageString(4420, nPaddedLength);
420c2c66affSColin Finck     if (pUserInfo->usri4_acct_expires == TIMEQ_FOREVER)
42188f899e1SEric Kohl         PrintMessageString(4305);
422c2c66affSColin Finck     else
423c2c66affSColin Finck         PrintDateTime(pUserInfo->usri4_acct_expires);
424c2c66affSColin Finck     ConPuts(StdOut, L"\n\n");
425c2c66affSColin Finck 
426050db4faSEric Kohl     PrintPaddedMessageString(4421, nPaddedLength);
427c2c66affSColin Finck     dwLastSet = GetTimeInSeconds() - pUserInfo->usri4_password_age;
428c2c66affSColin Finck     PrintDateTime(dwLastSet);
429e3d000c3SMarian Schubert     ConPuts(StdOut, L"\n");
430c2c66affSColin Finck 
431050db4faSEric Kohl     PrintPaddedMessageString(4422, nPaddedLength);
432c2c66affSColin Finck     if ((pUserInfo->usri4_flags & UF_DONT_EXPIRE_PASSWD) || pUserModals->usrmod0_max_passwd_age == TIMEQ_FOREVER)
43388f899e1SEric Kohl         PrintMessageString(4305);
434c2c66affSColin Finck     else
435c2c66affSColin Finck         PrintDateTime(dwLastSet + pUserModals->usrmod0_max_passwd_age);
436c2c66affSColin Finck     ConPuts(StdOut, L"\n");
437c2c66affSColin Finck 
438050db4faSEric Kohl     PrintPaddedMessageString(4423, nPaddedLength);
439c2c66affSColin Finck     PrintDateTime(dwLastSet + pUserModals->usrmod0_min_passwd_age);
440e3d000c3SMarian Schubert     ConPuts(StdOut, L"\n");
441c2c66affSColin Finck 
442050db4faSEric Kohl     PrintPaddedMessageString(4437, nPaddedLength);
44388f899e1SEric Kohl     PrintMessageString((pUserInfo->usri4_flags & UF_PASSWD_NOTREQD) ? 4301 : 4300);
444c2c66affSColin Finck     ConPuts(StdOut, L"\n");
445c2c66affSColin Finck 
446050db4faSEric Kohl     PrintPaddedMessageString(4438, nPaddedLength);
44788f899e1SEric Kohl     PrintMessageString((pUserInfo->usri4_flags & UF_PASSWD_CANT_CHANGE) ? 4301 : 4300);
448c2c66affSColin Finck     ConPuts(StdOut, L"\n\n");
449c2c66affSColin Finck 
450050db4faSEric Kohl     PrintPaddedMessageString(4424, nPaddedLength);
451c2c66affSColin Finck     if (pUserInfo->usri4_workstations == NULL || wcslen(pUserInfo->usri4_workstations) == 0)
45288f899e1SEric Kohl         PrintMessageString(4302);
453c2c66affSColin Finck     else
454c2c66affSColin Finck         ConPrintf(StdOut, L"%s", pUserInfo->usri4_workstations);
455c2c66affSColin Finck     ConPuts(StdOut, L"\n");
456c2c66affSColin Finck 
457050db4faSEric Kohl     PrintPaddedMessageString(4429, nPaddedLength);
458c2c66affSColin Finck     ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_script_path);
459c2c66affSColin Finck 
460050db4faSEric Kohl     PrintPaddedMessageString(4439, nPaddedLength);
461c2c66affSColin Finck     ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_profile);
462c2c66affSColin Finck 
463050db4faSEric Kohl     PrintPaddedMessageString(4436, nPaddedLength);
464c2c66affSColin Finck     ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_home_dir);
465c2c66affSColin Finck 
466050db4faSEric Kohl     PrintPaddedMessageString(4430, nPaddedLength);
467c2c66affSColin Finck     if (pUserInfo->usri4_last_logon == 0)
46888f899e1SEric Kohl         PrintMessageString(4305);
469c2c66affSColin Finck     else
470c2c66affSColin Finck         PrintDateTime(pUserInfo->usri4_last_logon);
471c2c66affSColin Finck     ConPuts(StdOut, L"\n\n");
472c2c66affSColin Finck 
473050db4faSEric Kohl     PrintPaddedMessageString(4432, nPaddedLength);
474c2c66affSColin Finck     if (pUserInfo->usri4_logon_hours == NULL)
4754cf5013aSEric Kohl     {
47688f899e1SEric Kohl         PrintMessageString(4302);
4774cf5013aSEric Kohl         ConPuts(StdOut, L"\n");
4784cf5013aSEric Kohl     }
4794cf5013aSEric Kohl     else
4804cf5013aSEric Kohl     {
4814cf5013aSEric Kohl         PrintLogonHours(pUserInfo->usri4_units_per_week,
4824cf5013aSEric Kohl                         pUserInfo->usri4_logon_hours,
4834cf5013aSEric Kohl                         nPaddedLength);
4844cf5013aSEric Kohl     }
485c2c66affSColin Finck 
486c2c66affSColin Finck     ConPuts(StdOut, L"\n");
487050db4faSEric Kohl     PrintPaddedMessageString(4427, nPaddedLength);
488c2c66affSColin Finck     if (dwLocalGroupTotal != 0 && pLocalGroupInfo != NULL)
489c2c66affSColin Finck     {
490c2c66affSColin Finck         for (i = 0; i < dwLocalGroupTotal; i++)
491c2c66affSColin Finck         {
492c2c66affSColin Finck             if (i != 0)
493c2c66affSColin Finck                 PrintPadding(L' ', nPaddedLength);
494c2c66affSColin Finck             ConPrintf(StdOut, L"*%s\n", pLocalGroupInfo[i].lgrui0_name);
495c2c66affSColin Finck         }
496c2c66affSColin Finck     }
497c2c66affSColin Finck     else
498c2c66affSColin Finck     {
499c2c66affSColin Finck         ConPuts(StdOut, L"\n");
500c2c66affSColin Finck     }
501c2c66affSColin Finck 
502050db4faSEric Kohl     PrintPaddedMessageString(4431, nPaddedLength);
503c2c66affSColin Finck     if (dwGroupTotal != 0 && pGroupInfo != NULL)
504c2c66affSColin Finck     {
505c2c66affSColin Finck         for (i = 0; i < dwGroupTotal; i++)
506c2c66affSColin Finck         {
507c2c66affSColin Finck             if (i != 0)
508c2c66affSColin Finck                 PrintPadding(L' ', nPaddedLength);
509c2c66affSColin Finck             ConPrintf(StdOut, L"*%s\n", pGroupInfo[i].grui0_name);
510c2c66affSColin Finck         }
511c2c66affSColin Finck     }
512c2c66affSColin Finck     else
513c2c66affSColin Finck     {
514c2c66affSColin Finck         ConPuts(StdOut, L"\n");
515c2c66affSColin Finck     }
516c2c66affSColin Finck 
517c2c66affSColin Finck done:
518c2c66affSColin Finck     if (pGroupInfo != NULL)
519c2c66affSColin Finck         NetApiBufferFree(pGroupInfo);
520c2c66affSColin Finck 
521c2c66affSColin Finck     if (pLocalGroupInfo != NULL)
522c2c66affSColin Finck         NetApiBufferFree(pLocalGroupInfo);
523c2c66affSColin Finck 
524c2c66affSColin Finck     if (pUserModals != NULL)
525c2c66affSColin Finck         NetApiBufferFree(pUserModals);
526c2c66affSColin Finck 
527c2c66affSColin Finck     if (pUserInfo != NULL)
528c2c66affSColin Finck         NetApiBufferFree(pUserInfo);
529c2c66affSColin Finck 
530c2c66affSColin Finck     return NERR_Success;
531c2c66affSColin Finck }
532c2c66affSColin Finck 
533c2c66affSColin Finck 
534c2c66affSColin Finck static
535c2c66affSColin Finck VOID
ReadPassword(LPWSTR * lpPassword,LPBOOL lpAllocated)536c2c66affSColin Finck ReadPassword(
537c2c66affSColin Finck     LPWSTR *lpPassword,
538c2c66affSColin Finck     LPBOOL lpAllocated)
539c2c66affSColin Finck {
540c2c66affSColin Finck     WCHAR szPassword1[PWLEN + 1];
541c2c66affSColin Finck     WCHAR szPassword2[PWLEN + 1];
542c2c66affSColin Finck     LPWSTR ptr;
543c2c66affSColin Finck 
544c2c66affSColin Finck     *lpAllocated = FALSE;
545c2c66affSColin Finck 
546c2c66affSColin Finck     while (TRUE)
547c2c66affSColin Finck     {
5485563525aSEric Kohl         PrintMessageString(4358);
549c2c66affSColin Finck         ReadFromConsole(szPassword1, PWLEN + 1, FALSE);
550c2c66affSColin Finck         ConPuts(StdOut, L"\n");
551c2c66affSColin Finck 
5525563525aSEric Kohl         PrintMessageString(4361);
553c2c66affSColin Finck         ReadFromConsole(szPassword2, PWLEN + 1, FALSE);
554c2c66affSColin Finck         ConPuts(StdOut, L"\n");
555c2c66affSColin Finck 
556c2c66affSColin Finck         if (wcslen(szPassword1) == wcslen(szPassword2) &&
557c2c66affSColin Finck             wcscmp(szPassword1, szPassword2) == 0)
558c2c66affSColin Finck         {
559c2c66affSColin Finck             ptr = HeapAlloc(GetProcessHeap(),
560c2c66affSColin Finck                             0,
561c2c66affSColin Finck                             (wcslen(szPassword1) + 1) * sizeof(WCHAR));
562c2c66affSColin Finck             if (ptr != NULL)
563c2c66affSColin Finck             {
564c2c66affSColin Finck                 wcscpy(ptr, szPassword1);
565c2c66affSColin Finck                 *lpPassword = ptr;
566c2c66affSColin Finck                 *lpAllocated = TRUE;
567c2c66affSColin Finck                 return;
568c2c66affSColin Finck             }
569c2c66affSColin Finck         }
570c2c66affSColin Finck         else
571c2c66affSColin Finck         {
572c2c66affSColin Finck             ConPuts(StdOut, L"\n");
5735563525aSEric Kohl             PrintMessageString(3728);
574c2c66affSColin Finck             *lpPassword = NULL;
575c2c66affSColin Finck         }
576c2c66affSColin Finck     }
577c2c66affSColin Finck }
578c2c66affSColin Finck 
579c2c66affSColin Finck 
580b4969dc0SEric Kohl static
581b4969dc0SEric Kohl VOID
GenerateRandomPassword(LPWSTR * lpPassword,LPBOOL lpAllocated)582b4969dc0SEric Kohl GenerateRandomPassword(
583b4969dc0SEric Kohl     LPWSTR *lpPassword,
584b4969dc0SEric Kohl     LPBOOL lpAllocated)
585b4969dc0SEric Kohl {
586b4969dc0SEric Kohl     LPWSTR pPassword = NULL;
587b4969dc0SEric Kohl     INT nCharsLen, i, nLength = 8;
588b4969dc0SEric Kohl 
589b4969dc0SEric Kohl     srand(GetTickCount());
590b4969dc0SEric Kohl 
591b4969dc0SEric Kohl     pPassword = HeapAlloc(GetProcessHeap(),
592b4969dc0SEric Kohl                           HEAP_ZERO_MEMORY,
593b4969dc0SEric Kohl                           (nLength + 1) * sizeof(WCHAR));
594b4969dc0SEric Kohl     if (pPassword == NULL)
595b4969dc0SEric Kohl         return;
596b4969dc0SEric Kohl 
597b4969dc0SEric Kohl     nCharsLen = wcslen(szPasswordChars);
598b4969dc0SEric Kohl 
599b4969dc0SEric Kohl     for (i = 0; i < nLength; i++)
600b4969dc0SEric Kohl     {
601b4969dc0SEric Kohl         pPassword[i] = szPasswordChars[rand() % nCharsLen];
602b4969dc0SEric Kohl     }
603b4969dc0SEric Kohl 
604b4969dc0SEric Kohl     *lpPassword = pPassword;
605b4969dc0SEric Kohl     *lpAllocated = TRUE;
606b4969dc0SEric Kohl }
607b4969dc0SEric Kohl 
608b4969dc0SEric Kohl 
609add1be24SEric Kohl static
610add1be24SEric Kohl NET_API_STATUS
BuildWorkstationsList(_Out_ PWSTR * pWorkstationsList,_In_ PWSTR pRaw)611add1be24SEric Kohl BuildWorkstationsList(
612add1be24SEric Kohl     _Out_ PWSTR *pWorkstationsList,
613add1be24SEric Kohl     _In_ PWSTR pRaw)
614add1be24SEric Kohl {
615add1be24SEric Kohl     BOOL isLastSep, isSep;
616add1be24SEric Kohl     INT i, j;
617add1be24SEric Kohl     WCHAR c;
618add1be24SEric Kohl     INT nLength = 0;
619add1be24SEric Kohl     INT nArgs = 0;
620add1be24SEric Kohl     INT nRawLength;
621add1be24SEric Kohl     PWSTR pList;
622add1be24SEric Kohl 
623add1be24SEric Kohl     /* Check for invalid characters in the raw string */
624add1be24SEric Kohl     if (wcspbrk(pRaw, L"/[]=?\\+:.") != NULL)
625add1be24SEric Kohl         return 3952;
626add1be24SEric Kohl 
627add1be24SEric Kohl     /* Count the number of workstations in the list and
628add1be24SEric Kohl      * the required buffer size */
629add1be24SEric Kohl     isLastSep = FALSE;
630add1be24SEric Kohl     isSep = FALSE;
631add1be24SEric Kohl     nRawLength = wcslen(pRaw);
632add1be24SEric Kohl     for (i = 0; i < nRawLength; i++)
633add1be24SEric Kohl     {
634add1be24SEric Kohl         c = pRaw[i];
635add1be24SEric Kohl         if (c == L',' || c == L';')
636add1be24SEric Kohl             isSep = TRUE;
637add1be24SEric Kohl 
638add1be24SEric Kohl         if (isSep == TRUE)
639add1be24SEric Kohl         {
640add1be24SEric Kohl             if ((isLastSep == FALSE) && (i != 0) && (i != nRawLength - 1))
641add1be24SEric Kohl                 nLength++;
642add1be24SEric Kohl         }
643add1be24SEric Kohl         else
644add1be24SEric Kohl         {
645add1be24SEric Kohl             nLength++;
646add1be24SEric Kohl 
647add1be24SEric Kohl             if (isLastSep == TRUE || (isLastSep == FALSE && i == 0))
648add1be24SEric Kohl                 nArgs++;
649add1be24SEric Kohl         }
650add1be24SEric Kohl 
651add1be24SEric Kohl         isLastSep = isSep;
652add1be24SEric Kohl         isSep = FALSE;
653add1be24SEric Kohl     }
654add1be24SEric Kohl 
655add1be24SEric Kohl     nLength++;
656add1be24SEric Kohl 
657add1be24SEric Kohl     /* Leave, if there are no workstations in the list */
658add1be24SEric Kohl     if (nArgs == 0)
659add1be24SEric Kohl     {
660add1be24SEric Kohl         pWorkstationsList = NULL;
661add1be24SEric Kohl         return NERR_Success;
662add1be24SEric Kohl     }
663add1be24SEric Kohl 
664add1be24SEric Kohl     /* Fail if there are more than eight workstations in the list */
665add1be24SEric Kohl     if (nArgs > 8)
666add1be24SEric Kohl         return 3951;
667add1be24SEric Kohl 
668add1be24SEric Kohl     /* Allocate the buffer for the clean workstation list */
669add1be24SEric Kohl     pList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nLength * sizeof(WCHAR));
670add1be24SEric Kohl     if (pList == NULL)
671add1be24SEric Kohl         return ERROR_NOT_ENOUGH_MEMORY;
672add1be24SEric Kohl 
673add1be24SEric Kohl     /* Build the clean workstation list */
674add1be24SEric Kohl     isLastSep = FALSE;
675add1be24SEric Kohl     isSep = FALSE;
676add1be24SEric Kohl     nRawLength = wcslen(pRaw);
677add1be24SEric Kohl     for (i = 0, j = 0; i < nRawLength; i++)
678add1be24SEric Kohl     {
679add1be24SEric Kohl         c = pRaw[i];
680add1be24SEric Kohl         if (c == L',' || c == L';')
681add1be24SEric Kohl             isSep = TRUE;
682add1be24SEric Kohl 
683add1be24SEric Kohl         if (isSep == TRUE)
684add1be24SEric Kohl         {
685add1be24SEric Kohl             if ((isLastSep == FALSE) && (i != 0) && (i != nRawLength - 1))
686add1be24SEric Kohl             {
687add1be24SEric Kohl                 pList[j] = L',';
688add1be24SEric Kohl                 j++;
689add1be24SEric Kohl             }
690add1be24SEric Kohl         }
691add1be24SEric Kohl         else
692add1be24SEric Kohl         {
693add1be24SEric Kohl             pList[j] = c;
694add1be24SEric Kohl             j++;
695add1be24SEric Kohl 
696add1be24SEric Kohl             if (isLastSep == TRUE || (isLastSep == FALSE && i == 0))
697add1be24SEric Kohl                 nArgs++;
698add1be24SEric Kohl         }
699add1be24SEric Kohl 
700add1be24SEric Kohl         isLastSep = isSep;
701add1be24SEric Kohl         isSep = FALSE;
702add1be24SEric Kohl     }
703add1be24SEric Kohl 
704add1be24SEric Kohl     *pWorkstationsList = pList;
705add1be24SEric Kohl 
706add1be24SEric Kohl     return NERR_Success;
707add1be24SEric Kohl }
708add1be24SEric Kohl 
709add1be24SEric Kohl 
710bf76e1bfSEric Kohl static
711bf76e1bfSEric Kohl BOOL
ReadNumber(PWSTR * s,PWORD pwValue)712bf76e1bfSEric Kohl ReadNumber(
713bf76e1bfSEric Kohl     PWSTR *s,
714bf76e1bfSEric Kohl     PWORD pwValue)
715bf76e1bfSEric Kohl {
716bf76e1bfSEric Kohl     if (!iswdigit(**s))
717bf76e1bfSEric Kohl         return FALSE;
718bf76e1bfSEric Kohl 
719bf76e1bfSEric Kohl     while (iswdigit(**s))
720bf76e1bfSEric Kohl     {
721bf76e1bfSEric Kohl         *pwValue = *pwValue * 10 + **s - L'0';
722bf76e1bfSEric Kohl         (*s)++;
723bf76e1bfSEric Kohl     }
724bf76e1bfSEric Kohl 
725bf76e1bfSEric Kohl     return TRUE;
726bf76e1bfSEric Kohl }
727bf76e1bfSEric Kohl 
728bf76e1bfSEric Kohl 
729bf76e1bfSEric Kohl static
730bf76e1bfSEric Kohl BOOL
ReadSeparator(PWSTR * s)731bf76e1bfSEric Kohl ReadSeparator(
732bf76e1bfSEric Kohl     PWSTR *s)
733bf76e1bfSEric Kohl {
734bf76e1bfSEric Kohl     if (**s == L'/' || **s == L'.')
735bf76e1bfSEric Kohl     {
736bf76e1bfSEric Kohl         (*s)++;
737bf76e1bfSEric Kohl         return TRUE;
738bf76e1bfSEric Kohl     }
739bf76e1bfSEric Kohl 
740bf76e1bfSEric Kohl     return FALSE;
741bf76e1bfSEric Kohl }
742bf76e1bfSEric Kohl 
743bf76e1bfSEric Kohl 
744bf76e1bfSEric Kohl static
745bf76e1bfSEric Kohl BOOL
ParseDate(PWSTR s,PULONG pSeconds)746bf76e1bfSEric Kohl ParseDate(
747bf76e1bfSEric Kohl     PWSTR s,
748bf76e1bfSEric Kohl     PULONG pSeconds)
749bf76e1bfSEric Kohl {
750bf76e1bfSEric Kohl     SYSTEMTIME SystemTime = {0};
751bf76e1bfSEric Kohl     FILETIME LocalFileTime, FileTime;
752bf76e1bfSEric Kohl     LARGE_INTEGER Time;
753bf76e1bfSEric Kohl     INT nDateFormat = 0;
754bf76e1bfSEric Kohl     PWSTR p = s;
755bf76e1bfSEric Kohl 
756bf76e1bfSEric Kohl     if (!*s)
757bf76e1bfSEric Kohl         return FALSE;
758bf76e1bfSEric Kohl 
759bf76e1bfSEric Kohl     GetLocaleInfoW(LOCALE_USER_DEFAULT,
760bf76e1bfSEric Kohl                    LOCALE_IDATE,
761bf76e1bfSEric Kohl                    (PWSTR)&nDateFormat,
762bf76e1bfSEric Kohl                    sizeof(INT));
763bf76e1bfSEric Kohl 
764bf76e1bfSEric Kohl     switch (nDateFormat)
765bf76e1bfSEric Kohl     {
766bf76e1bfSEric Kohl         case 0: /* mmddyy */
767bf76e1bfSEric Kohl         default:
768bf76e1bfSEric Kohl             if (!ReadNumber(&p, &SystemTime.wMonth))
769bf76e1bfSEric Kohl                 return FALSE;
770bf76e1bfSEric Kohl             if (!ReadSeparator(&p))
771bf76e1bfSEric Kohl                 return FALSE;
772bf76e1bfSEric Kohl             if (!ReadNumber(&p, &SystemTime.wDay))
773bf76e1bfSEric Kohl                 return FALSE;
774bf76e1bfSEric Kohl             if (!ReadSeparator(&p))
775bf76e1bfSEric Kohl                 return FALSE;
776bf76e1bfSEric Kohl             if (!ReadNumber(&p, &SystemTime.wYear))
777bf76e1bfSEric Kohl                 return FALSE;
778bf76e1bfSEric Kohl             break;
779bf76e1bfSEric Kohl 
780bf76e1bfSEric Kohl         case 1: /* ddmmyy */
781bf76e1bfSEric Kohl             if (!ReadNumber(&p, &SystemTime.wDay))
782bf76e1bfSEric Kohl                 return FALSE;
783bf76e1bfSEric Kohl             if (!ReadSeparator(&p))
784bf76e1bfSEric Kohl                 return FALSE;
785bf76e1bfSEric Kohl             if (!ReadNumber(&p, &SystemTime.wMonth))
786bf76e1bfSEric Kohl                 return FALSE;
787bf76e1bfSEric Kohl             if (!ReadSeparator(&p))
788bf76e1bfSEric Kohl                 return FALSE;
789bf76e1bfSEric Kohl             if (!ReadNumber(&p, &SystemTime.wYear))
790bf76e1bfSEric Kohl                 return FALSE;
791bf76e1bfSEric Kohl             break;
792bf76e1bfSEric Kohl 
793bf76e1bfSEric Kohl         case 2: /* yymmdd */
794bf76e1bfSEric Kohl             if (!ReadNumber(&p, &SystemTime.wYear))
795bf76e1bfSEric Kohl                 return FALSE;
796bf76e1bfSEric Kohl             if (!ReadSeparator(&p))
797bf76e1bfSEric Kohl                 return FALSE;
798bf76e1bfSEric Kohl             if (!ReadNumber(&p, &SystemTime.wMonth))
799bf76e1bfSEric Kohl                 return FALSE;
800bf76e1bfSEric Kohl             if (!ReadSeparator(&p))
801bf76e1bfSEric Kohl                 return FALSE;
802bf76e1bfSEric Kohl             if (!ReadNumber(&p, &SystemTime.wDay))
803bf76e1bfSEric Kohl                 return FALSE;
804bf76e1bfSEric Kohl             break;
805bf76e1bfSEric Kohl     }
806bf76e1bfSEric Kohl 
807bf76e1bfSEric Kohl     /* if only entered two digits: */
808bf76e1bfSEric Kohl     /*   assume 2000's if value less than 80 */
809bf76e1bfSEric Kohl     /*   assume 1900's if value greater or equal 80 */
810bf76e1bfSEric Kohl     if (SystemTime.wYear <= 99)
811bf76e1bfSEric Kohl     {
812bf76e1bfSEric Kohl         if (SystemTime.wYear >= 80)
813bf76e1bfSEric Kohl             SystemTime.wYear += 1900;
814bf76e1bfSEric Kohl         else
815bf76e1bfSEric Kohl             SystemTime.wYear += 2000;
816bf76e1bfSEric Kohl     }
817bf76e1bfSEric Kohl 
818bf76e1bfSEric Kohl     if (!SystemTimeToFileTime(&SystemTime, &LocalFileTime))
819bf76e1bfSEric Kohl         return FALSE;
820bf76e1bfSEric Kohl 
821bf76e1bfSEric Kohl     if (!LocalFileTimeToFileTime(&LocalFileTime, &FileTime))
822bf76e1bfSEric Kohl         return FALSE;
823bf76e1bfSEric Kohl 
824bf76e1bfSEric Kohl     Time.u.LowPart = FileTime.dwLowDateTime;
825bf76e1bfSEric Kohl     Time.u.HighPart = FileTime.dwHighDateTime;
826bf76e1bfSEric Kohl 
827bf76e1bfSEric Kohl     if (!RtlTimeToSecondsSince1970(&Time, pSeconds))
828bf76e1bfSEric Kohl         return FALSE;
829bf76e1bfSEric Kohl 
830bf76e1bfSEric Kohl     return TRUE;
831bf76e1bfSEric Kohl }
832bf76e1bfSEric Kohl 
833bf76e1bfSEric Kohl 
834611e6d7dSEric Kohl static
835ccd95b98SEric Kohl BOOL
ParseHour(PWSTR pszString,PWSTR * AmPmArray,PLONG plHour)836ccd95b98SEric Kohl ParseHour(
837ccd95b98SEric Kohl     PWSTR pszString,
838df31f870SEric Kohl     PWSTR *AmPmArray,
839e5b635edSEric Kohl     PLONG plHour)
840ccd95b98SEric Kohl {
841ccd95b98SEric Kohl     PWCHAR pChar;
842e5b635edSEric Kohl     LONG lHour = 0;
843ccd95b98SEric Kohl 
844ccd95b98SEric Kohl     if (!iswdigit(pszString[0]))
845ccd95b98SEric Kohl         return FALSE;
846ccd95b98SEric Kohl 
847ccd95b98SEric Kohl     pChar = pszString;
848ccd95b98SEric Kohl     while (iswdigit(*pChar))
849ccd95b98SEric Kohl     {
850e5b635edSEric Kohl         lHour = lHour * 10 + *pChar - L'0';
851ccd95b98SEric Kohl         pChar++;
852ccd95b98SEric Kohl     }
853ccd95b98SEric Kohl 
854e5b635edSEric Kohl     if (lHour > 24)
855ccd95b98SEric Kohl         return FALSE;
856ccd95b98SEric Kohl 
857e5b635edSEric Kohl     if (lHour == 24)
858e5b635edSEric Kohl         lHour = 0;
859ccd95b98SEric Kohl 
860ccd95b98SEric Kohl     if ((*pChar != UNICODE_NULL) &&
861e5b635edSEric Kohl         (lHour >= 1) &&
862e5b635edSEric Kohl         (lHour <= 12))
863ccd95b98SEric Kohl     {
864df31f870SEric Kohl         if ((_wcsicmp(pChar, AmPmArray[0]) == 0) ||
865df31f870SEric Kohl             (_wcsicmp(pChar, AmPmArray[1]) == 0))
866ccd95b98SEric Kohl         {
867e5b635edSEric Kohl             if (lHour == 12)
868e5b635edSEric Kohl                 lHour = 0;
869ccd95b98SEric Kohl         }
870df31f870SEric Kohl         else if ((_wcsicmp(pChar, AmPmArray[2]) == 0) ||
871df31f870SEric Kohl                  (_wcsicmp(pChar, AmPmArray[3]) == 0))
872ccd95b98SEric Kohl         {
873e5b635edSEric Kohl             if (lHour != 12)
874e5b635edSEric Kohl                 lHour += 12;
875ccd95b98SEric Kohl         }
876ccd95b98SEric Kohl         else
877ccd95b98SEric Kohl         {
878ccd95b98SEric Kohl             return FALSE;
879ccd95b98SEric Kohl         }
880ccd95b98SEric Kohl     }
881ccd95b98SEric Kohl 
882e5b635edSEric Kohl     *plHour = lHour;
883ccd95b98SEric Kohl 
884ccd95b98SEric Kohl     return TRUE;
885ccd95b98SEric Kohl }
886ccd95b98SEric Kohl 
887ccd95b98SEric Kohl 
888ccd95b98SEric Kohl static
889ccd95b98SEric Kohl BOOL
ParseDay(PWSTR pszString,PWSTR * ShortDays,PWSTR * LongDays,PDWORD pdwDay)890ccd95b98SEric Kohl ParseDay(
891ccd95b98SEric Kohl     PWSTR pszString,
892df31f870SEric Kohl     PWSTR *ShortDays,
893df31f870SEric Kohl     PWSTR *LongDays,
894ccd95b98SEric Kohl     PDWORD pdwDay)
895ccd95b98SEric Kohl {
896ccd95b98SEric Kohl     DWORD i;
897ccd95b98SEric Kohl 
898df31f870SEric Kohl     for (i = 0; i < 7; i++)
899ccd95b98SEric Kohl     {
900df31f870SEric Kohl         if (_wcsicmp(pszString, ShortDays[i]) == 0 ||
901df31f870SEric Kohl             _wcsicmp(pszString, LongDays[i]) == 0)
902ccd95b98SEric Kohl         {
903ccd95b98SEric Kohl             *pdwDay = i;
904ccd95b98SEric Kohl             return TRUE;
905ccd95b98SEric Kohl         }
906ccd95b98SEric Kohl     }
907ccd95b98SEric Kohl 
908ccd95b98SEric Kohl     return FALSE;
909ccd95b98SEric Kohl }
910ccd95b98SEric Kohl 
911ccd95b98SEric Kohl 
912ccd95b98SEric Kohl static
913611e6d7dSEric Kohl DWORD
LocalToGmtHour(LONG lLocalHour,LONG lBias)914d0d7c5f0SEric Kohl LocalToGmtHour(
915d0d7c5f0SEric Kohl     LONG lLocalHour,
916d0d7c5f0SEric Kohl     LONG lBias)
917d0d7c5f0SEric Kohl {
918d0d7c5f0SEric Kohl     LONG lGmtHour;
919d0d7c5f0SEric Kohl 
920d0d7c5f0SEric Kohl     lGmtHour = lLocalHour + lBias;
921d0d7c5f0SEric Kohl     if (lGmtHour < 0)
922d0d7c5f0SEric Kohl         lGmtHour += UNITS_PER_WEEK;
923d0d7c5f0SEric Kohl     else if (lGmtHour > UNITS_PER_WEEK)
924d0d7c5f0SEric Kohl         lGmtHour -= UNITS_PER_WEEK;
925d0d7c5f0SEric Kohl 
926d0d7c5f0SEric Kohl     return (DWORD)lGmtHour;
927d0d7c5f0SEric Kohl }
928d0d7c5f0SEric Kohl 
929d0d7c5f0SEric Kohl 
930d0d7c5f0SEric Kohl static
931d0d7c5f0SEric Kohl DWORD
ParseLogonHours(PWSTR pszParams,PBYTE * ppLogonBitmap,PDWORD pdwUnitsPerWeek)932611e6d7dSEric Kohl ParseLogonHours(
933611e6d7dSEric Kohl     PWSTR pszParams,
934ccd95b98SEric Kohl     PBYTE *ppLogonBitmap,
935611e6d7dSEric Kohl     PDWORD pdwUnitsPerWeek)
936611e6d7dSEric Kohl {
937e5b635edSEric Kohl     TIME_ZONE_INFORMATION TimeZoneInformation;
938ccd95b98SEric Kohl     PBYTE pLogonBitmap = NULL;
939611e6d7dSEric Kohl     DWORD dwError = ERROR_SUCCESS;
940ccd95b98SEric Kohl     WCHAR szBuffer[32];
941ccd95b98SEric Kohl     PWSTR ptr1, ptr2;
942ccd95b98SEric Kohl     WCHAR prevSep, nextSep;
943e5b635edSEric Kohl     DWORD dwStartDay, dwEndDay, i, j;
944e5b635edSEric Kohl     LONG lStartHour, lEndHour, lBias;
945ccd95b98SEric Kohl     BYTE DayBitmap;
946ccd95b98SEric Kohl     BYTE HourBitmap[6];
947df31f870SEric Kohl     LPWSTR ShortDays[7] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
948df31f870SEric Kohl     LPWSTR LongDays[7] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
949df31f870SEric Kohl     LPWSTR AmPmArray[4] = {NULL, NULL, NULL, NULL};
950611e6d7dSEric Kohl 
951e5b635edSEric Kohl     GetTimeZoneInformation(&TimeZoneInformation);
952e5b635edSEric Kohl     lBias = TimeZoneInformation.Bias / 60;
953e5b635edSEric Kohl 
954ccd95b98SEric Kohl     pLogonBitmap = HeapAlloc(GetProcessHeap(),
955611e6d7dSEric Kohl                              HEAP_ZERO_MEMORY,
956611e6d7dSEric Kohl                              UNITS_PER_WEEK / 8);
957ccd95b98SEric Kohl     if (pLogonBitmap == NULL)
958611e6d7dSEric Kohl         return ERROR_OUTOFMEMORY;
959611e6d7dSEric Kohl 
960611e6d7dSEric Kohl     if (*pszParams == UNICODE_NULL)
961611e6d7dSEric Kohl     {
962611e6d7dSEric Kohl         goto done;
963611e6d7dSEric Kohl     }
964611e6d7dSEric Kohl 
965*e4930be4STimo Kreuzer     if (_wcsicmp(pszParams, L"all") == 0)
966611e6d7dSEric Kohl     {
967ccd95b98SEric Kohl         FillMemory(pLogonBitmap, UNITS_PER_WEEK / 8, 0xFF);
968611e6d7dSEric Kohl         goto done;
969611e6d7dSEric Kohl     }
970611e6d7dSEric Kohl 
971df31f870SEric Kohl     for (i = 0; i < 7; i++)
972df31f870SEric Kohl     {
973df31f870SEric Kohl         FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
974df31f870SEric Kohl                        FORMAT_MESSAGE_FROM_HMODULE |
975df31f870SEric Kohl                        FORMAT_MESSAGE_IGNORE_INSERTS,
976df31f870SEric Kohl                        hModuleNetMsg,
977df31f870SEric Kohl                        4314 + i,
978df31f870SEric Kohl                        LANG_USER_DEFAULT,
979df31f870SEric Kohl                        (LPWSTR)&ShortDays[i],
980df31f870SEric Kohl                        0,
981df31f870SEric Kohl                        NULL);
982df31f870SEric Kohl 
983df31f870SEric Kohl         FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
984df31f870SEric Kohl                        FORMAT_MESSAGE_FROM_HMODULE |
985df31f870SEric Kohl                        FORMAT_MESSAGE_IGNORE_INSERTS,
986df31f870SEric Kohl                        hModuleNetMsg,
987df31f870SEric Kohl                        4307 + i,
988df31f870SEric Kohl                        LANG_USER_DEFAULT,
989df31f870SEric Kohl                        (LPWSTR)&LongDays[i],
990df31f870SEric Kohl                        0,
991df31f870SEric Kohl                        NULL);
992df31f870SEric Kohl     }
993df31f870SEric Kohl 
994df31f870SEric Kohl     for (i = 0; i < 4; i++)
995df31f870SEric Kohl     {
996df31f870SEric Kohl         FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
997df31f870SEric Kohl                        FORMAT_MESSAGE_FROM_HMODULE |
998df31f870SEric Kohl                        FORMAT_MESSAGE_IGNORE_INSERTS,
999df31f870SEric Kohl                        hModuleNetMsg,
1000df31f870SEric Kohl                        4322 + i,
1001df31f870SEric Kohl                        LANG_USER_DEFAULT,
1002df31f870SEric Kohl                        (LPWSTR)&AmPmArray[i],
1003df31f870SEric Kohl                        0,
1004df31f870SEric Kohl                        NULL);
1005df31f870SEric Kohl     }
1006df31f870SEric Kohl 
1007ccd95b98SEric Kohl     ZeroMemory(&DayBitmap, sizeof(DayBitmap));
1008ccd95b98SEric Kohl     ZeroMemory(HourBitmap, sizeof(HourBitmap));
1009ccd95b98SEric Kohl 
1010ccd95b98SEric Kohl     ZeroMemory(szBuffer, sizeof(szBuffer));
1011ccd95b98SEric Kohl     ptr1 = pszParams;
1012ccd95b98SEric Kohl     ptr2 = szBuffer;
1013ccd95b98SEric Kohl     prevSep = UNICODE_NULL;
1014ccd95b98SEric Kohl     nextSep = UNICODE_NULL;
1015ccd95b98SEric Kohl     for (;;)
1016ccd95b98SEric Kohl     {
1017ccd95b98SEric Kohl         if (*ptr1 != L'-' && *ptr1 != L',' && *ptr1 != L';' && *ptr1 != UNICODE_NULL)
1018ccd95b98SEric Kohl         {
1019ccd95b98SEric Kohl             *ptr2 = *ptr1;
1020ccd95b98SEric Kohl             ptr2++;
1021ccd95b98SEric Kohl         }
1022ccd95b98SEric Kohl         else
1023ccd95b98SEric Kohl         {
1024ccd95b98SEric Kohl             prevSep = nextSep;
1025ccd95b98SEric Kohl             nextSep = *ptr1;
1026ccd95b98SEric Kohl 
1027ccd95b98SEric Kohl             if (prevSep != L'-')
1028ccd95b98SEric Kohl             {
1029e5b635edSEric Kohl                 /* Set first value */
1030ccd95b98SEric Kohl                 if (iswdigit(szBuffer[0]))
1031ccd95b98SEric Kohl                 {
1032e5b635edSEric Kohl                     /* Parse hour */
1033df31f870SEric Kohl                     if (!ParseHour(szBuffer, AmPmArray, &lStartHour))
1034ccd95b98SEric Kohl                     {
1035ccd95b98SEric Kohl                         dwError = 3769;
1036ccd95b98SEric Kohl                         break;
1037ccd95b98SEric Kohl                     }
1038ccd95b98SEric Kohl 
1039d0d7c5f0SEric Kohl                     SetBitValue(HourBitmap, LocalToGmtHour(lStartHour, lBias));
1040ccd95b98SEric Kohl                 }
1041ccd95b98SEric Kohl                 else
1042ccd95b98SEric Kohl                 {
1043e5b635edSEric Kohl                     /* Parse day */
1044df31f870SEric Kohl                     if (!ParseDay(szBuffer, ShortDays, LongDays, &dwStartDay))
1045ccd95b98SEric Kohl                     {
1046611e6d7dSEric Kohl                         dwError = 3768;
1047ccd95b98SEric Kohl                         break;
1048ccd95b98SEric Kohl                     }
1049ccd95b98SEric Kohl 
1050ccd95b98SEric Kohl                     SetBitValue(&DayBitmap, dwStartDay);
1051ccd95b98SEric Kohl                 }
1052ccd95b98SEric Kohl             }
1053ccd95b98SEric Kohl             else
1054ccd95b98SEric Kohl             {
1055e5b635edSEric Kohl                 /* Set second value */
1056ccd95b98SEric Kohl                 if (iswdigit(szBuffer[0]))
1057ccd95b98SEric Kohl                 {
1058e5b635edSEric Kohl                     /* Parse hour */
1059df31f870SEric Kohl                     if (!ParseHour(szBuffer, AmPmArray, &lEndHour))
1060ccd95b98SEric Kohl                     {
1061ccd95b98SEric Kohl                         dwError = 3769;
1062ccd95b98SEric Kohl                         break;
1063ccd95b98SEric Kohl                     }
1064ccd95b98SEric Kohl 
1065d0d7c5f0SEric Kohl                     if (lEndHour <= lStartHour)
1066e5b635edSEric Kohl                         lEndHour += HOURS_PER_DAY;
1067ccd95b98SEric Kohl 
1068d0d7c5f0SEric Kohl                     for (i = LocalToGmtHour(lStartHour, lBias); i < LocalToGmtHour(lEndHour, lBias); i++)
1069ccd95b98SEric Kohl                         SetBitValue(HourBitmap, i);
1070ccd95b98SEric Kohl                 }
1071ccd95b98SEric Kohl                 else
1072ccd95b98SEric Kohl                 {
1073e5b635edSEric Kohl                     /* Parse day */
1074df31f870SEric Kohl                     if (!ParseDay(szBuffer, ShortDays, LongDays, &dwEndDay))
1075ccd95b98SEric Kohl                     {
1076ccd95b98SEric Kohl                         dwError = 3768;
1077ccd95b98SEric Kohl                         break;
1078ccd95b98SEric Kohl                     }
1079ccd95b98SEric Kohl 
1080ccd95b98SEric Kohl                     if (dwEndDay <= dwStartDay)
1081ccd95b98SEric Kohl                         dwEndDay += DAYS_PER_WEEK;
1082ccd95b98SEric Kohl 
1083ccd95b98SEric Kohl                     for (i = dwStartDay; i <= dwEndDay; i++)
1084ccd95b98SEric Kohl                         SetBitValue(&DayBitmap, i % DAYS_PER_WEEK);
1085ccd95b98SEric Kohl                 }
1086ccd95b98SEric Kohl             }
1087ccd95b98SEric Kohl 
1088ccd95b98SEric Kohl             if (*ptr1 == L';' || *ptr1 == UNICODE_NULL)
1089ccd95b98SEric Kohl             {
1090e5b635edSEric Kohl                 /* Fill the logon hour bitmap */
1091ccd95b98SEric Kohl                 for (i = 0; i < DAYS_PER_WEEK; i++)
1092ccd95b98SEric Kohl                 {
1093ccd95b98SEric Kohl                     if (GetBitValue(&DayBitmap, i))
1094ccd95b98SEric Kohl                     {
1095ccd95b98SEric Kohl                         for (j = 0; j < 48; j++)
1096ccd95b98SEric Kohl                         {
1097ccd95b98SEric Kohl                             if (GetBitValue(HourBitmap, j))
1098ccd95b98SEric Kohl                                 SetBitValue(pLogonBitmap, ((i * HOURS_PER_DAY) + j) % UNITS_PER_WEEK);
1099ccd95b98SEric Kohl                         }
1100ccd95b98SEric Kohl                     }
1101ccd95b98SEric Kohl                 }
1102ccd95b98SEric Kohl 
1103e5b635edSEric Kohl                 /* Reset the Bitmaps */
1104ccd95b98SEric Kohl                 ZeroMemory(&DayBitmap, sizeof(DayBitmap));
1105ccd95b98SEric Kohl                 ZeroMemory(HourBitmap, sizeof(HourBitmap));
1106ccd95b98SEric Kohl             }
1107ccd95b98SEric Kohl 
1108ccd95b98SEric Kohl             if (*ptr1 == UNICODE_NULL)
1109ccd95b98SEric Kohl                 break;
1110ccd95b98SEric Kohl 
1111ccd95b98SEric Kohl             ZeroMemory(szBuffer, sizeof(szBuffer));
1112ccd95b98SEric Kohl             ptr2 = szBuffer;
1113ccd95b98SEric Kohl         }
1114ccd95b98SEric Kohl 
1115ccd95b98SEric Kohl         ptr1++;
1116ccd95b98SEric Kohl     }
1117ccd95b98SEric Kohl 
1118611e6d7dSEric Kohl done:
1119df31f870SEric Kohl     for (i = 0; i < 7; i++)
1120df31f870SEric Kohl     {
1121df31f870SEric Kohl         LocalFree(ShortDays[i]);
1122df31f870SEric Kohl         LocalFree(LongDays[i]);
1123df31f870SEric Kohl     }
1124df31f870SEric Kohl 
1125df31f870SEric Kohl     for (i = 0; i < 4; i++)
1126df31f870SEric Kohl     {
1127df31f870SEric Kohl         LocalFree(AmPmArray[i]);
1128df31f870SEric Kohl     }
1129df31f870SEric Kohl 
1130611e6d7dSEric Kohl     if (dwError == ERROR_SUCCESS)
1131611e6d7dSEric Kohl     {
1132ccd95b98SEric Kohl         *ppLogonBitmap = pLogonBitmap;
1133611e6d7dSEric Kohl         *pdwUnitsPerWeek = UNITS_PER_WEEK;
1134611e6d7dSEric Kohl     }
1135611e6d7dSEric Kohl     else
1136611e6d7dSEric Kohl     {
1137ccd95b98SEric Kohl         if (pLogonBitmap != NULL)
1138ccd95b98SEric Kohl             HeapFree(GetProcessHeap(), 0, pLogonBitmap);
1139ccd95b98SEric Kohl         *ppLogonBitmap = NULL;
1140ccd95b98SEric Kohl         *pdwUnitsPerWeek = 0;
1141611e6d7dSEric Kohl     }
1142611e6d7dSEric Kohl 
1143611e6d7dSEric Kohl     return dwError;
1144611e6d7dSEric Kohl }
1145611e6d7dSEric Kohl 
1146611e6d7dSEric Kohl 
1147c2c66affSColin Finck INT
cmdUser(INT argc,WCHAR ** argv)1148c2c66affSColin Finck cmdUser(
1149c2c66affSColin Finck     INT argc,
1150c2c66affSColin Finck     WCHAR **argv)
1151c2c66affSColin Finck {
1152c2c66affSColin Finck     INT i, j;
1153c2c66affSColin Finck     INT result = 0;
1154c2c66affSColin Finck     BOOL bAdd = FALSE;
1155c2c66affSColin Finck     BOOL bDelete = FALSE;
1156c2c66affSColin Finck #if 0
1157c2c66affSColin Finck     BOOL bDomain = FALSE;
1158c2c66affSColin Finck #endif
1159b4969dc0SEric Kohl     BOOL bRandomPassword = FALSE;
1160c2c66affSColin Finck     LPWSTR lpUserName = NULL;
1161c2c66affSColin Finck     LPWSTR lpPassword = NULL;
1162c2c66affSColin Finck     PUSER_INFO_4 pUserInfo = NULL;
1163c2c66affSColin Finck     USER_INFO_4 UserInfo;
1164add1be24SEric Kohl     LPWSTR pWorkstations = NULL;
1165c2c66affSColin Finck     LPWSTR p;
1166c2c66affSColin Finck     LPWSTR endptr;
1167c2c66affSColin Finck     DWORD value;
1168c2c66affSColin Finck     BOOL bPasswordAllocated = FALSE;
1169611e6d7dSEric Kohl     PBYTE pLogonHours = NULL;
1170611e6d7dSEric Kohl     DWORD dwUnitsPerWeek;
1171c2c66affSColin Finck     NET_API_STATUS Status;
1172c2c66affSColin Finck 
1173c2c66affSColin Finck     i = 2;
11744d8859cfSEric Kohl     if ((i < argc) && (argv[i][0] != L'/'))
1175c2c66affSColin Finck     {
1176c2c66affSColin Finck         lpUserName = argv[i];
1177c2c66affSColin Finck //        ConPrintf(StdOut, L"User: %s\n", lpUserName);
1178c2c66affSColin Finck         i++;
1179c2c66affSColin Finck     }
1180c2c66affSColin Finck 
11814d8859cfSEric Kohl     if ((i < argc) && (argv[i][0] != L'/'))
1182c2c66affSColin Finck     {
1183c2c66affSColin Finck         lpPassword = argv[i];
1184c2c66affSColin Finck //        ConPrintf(StdOut, L"Password: %s\n", lpPassword);
1185c2c66affSColin Finck         i++;
1186c2c66affSColin Finck     }
1187c2c66affSColin Finck 
1188c2c66affSColin Finck     for (j = i; j < argc; j++)
1189c2c66affSColin Finck     {
1190c2c66affSColin Finck         if (_wcsicmp(argv[j], L"/help") == 0)
1191c2c66affSColin Finck         {
11924e28e654SEric Kohl             PrintNetMessage(MSG_USER_HELP);
1193c2c66affSColin Finck             return 0;
1194c2c66affSColin Finck         }
1195c2c66affSColin Finck         else if (_wcsicmp(argv[j], L"/add") == 0)
1196c2c66affSColin Finck         {
1197c2c66affSColin Finck             bAdd = TRUE;
1198c2c66affSColin Finck         }
1199c2c66affSColin Finck         else if (_wcsicmp(argv[j], L"/delete") == 0)
1200c2c66affSColin Finck         {
1201c2c66affSColin Finck             bDelete = TRUE;
1202c2c66affSColin Finck         }
1203c2c66affSColin Finck         else if (_wcsicmp(argv[j], L"/domain") == 0)
1204c2c66affSColin Finck         {
120529bf2097SEric Kohl             ConPuts(StdErr, L"The /DOMAIN option is not supported yet.\n");
1206c2c66affSColin Finck #if 0
1207c2c66affSColin Finck             bDomain = TRUE;
1208c2c66affSColin Finck #endif
1209c2c66affSColin Finck         }
1210b4969dc0SEric Kohl         else if (_wcsicmp(argv[j], L"/random") == 0)
1211b4969dc0SEric Kohl         {
1212b4969dc0SEric Kohl             bRandomPassword = TRUE;
1213b4969dc0SEric Kohl             GenerateRandomPassword(&lpPassword,
1214b4969dc0SEric Kohl                                    &bPasswordAllocated);
1215b4969dc0SEric Kohl         }
1216c2c66affSColin Finck     }
1217c2c66affSColin Finck 
12184e28e654SEric Kohl     if (lpUserName == NULL && lpPassword == NULL)
12194e28e654SEric Kohl     {
12204e28e654SEric Kohl         Status = EnumerateUsers();
1221073607c2SMarat Nagayev         PrintMessageString(TranslateAppMessage(Status));
12224e28e654SEric Kohl         return 0;
12234e28e654SEric Kohl     }
1224611e6d7dSEric Kohl     else if (lpUserName != NULL && lpPassword == NULL && argc == 3)
12254e28e654SEric Kohl     {
12264e28e654SEric Kohl         Status = DisplayUser(lpUserName);
1227073607c2SMarat Nagayev         PrintMessageString(TranslateAppMessage(Status));
12284e28e654SEric Kohl         return 0;
12294e28e654SEric Kohl     }
12304e28e654SEric Kohl 
1231c2c66affSColin Finck     if (bAdd && bDelete)
1232c2c66affSColin Finck     {
1233c2c66affSColin Finck         result = 1;
1234c2c66affSColin Finck         goto done;
1235c2c66affSColin Finck     }
1236c2c66affSColin Finck 
1237c2c66affSColin Finck     /* Interactive password input */
1238c2c66affSColin Finck     if (lpPassword != NULL && wcscmp(lpPassword, L"*") == 0)
1239c2c66affSColin Finck     {
1240c2c66affSColin Finck         ReadPassword(&lpPassword,
1241c2c66affSColin Finck                      &bPasswordAllocated);
1242c2c66affSColin Finck     }
1243c2c66affSColin Finck 
1244c2c66affSColin Finck     if (!bAdd && !bDelete)
1245c2c66affSColin Finck     {
1246c2c66affSColin Finck         /* Modify the user */
1247c2c66affSColin Finck         Status = NetUserGetInfo(NULL,
1248c2c66affSColin Finck                                 lpUserName,
1249c2c66affSColin Finck                                 4,
1250c2c66affSColin Finck                                 (LPBYTE*)&pUserInfo);
1251c2c66affSColin Finck         if (Status != NERR_Success)
1252c2c66affSColin Finck         {
1253073607c2SMarat Nagayev             PrintMessageString(TranslateAppMessage(Status));
1254c2c66affSColin Finck             result = 1;
1255c2c66affSColin Finck             goto done;
1256c2c66affSColin Finck         }
1257c2c66affSColin Finck     }
1258073607c2SMarat Nagayev     else if (bAdd)
1259c2c66affSColin Finck     {
1260c2c66affSColin Finck         /* Add the user */
1261c2c66affSColin Finck         ZeroMemory(&UserInfo, sizeof(USER_INFO_4));
1262c2c66affSColin Finck 
1263c2c66affSColin Finck         UserInfo.usri4_name = lpUserName;
1264c2c66affSColin Finck         UserInfo.usri4_password = lpPassword;
1265c2c66affSColin Finck         UserInfo.usri4_flags = UF_SCRIPT | UF_NORMAL_ACCOUNT;
12668f63c209SEric Kohl         UserInfo.usri4_acct_expires = TIMEQ_FOREVER;
12674bbbc408SEric Kohl         UserInfo.usri4_primary_group_id = DOMAIN_GROUP_RID_USERS;
1268c2c66affSColin Finck 
1269c2c66affSColin Finck         pUserInfo = &UserInfo;
1270c2c66affSColin Finck     }
1271c2c66affSColin Finck 
1272c2c66affSColin Finck     for (j = i; j < argc; j++)
1273c2c66affSColin Finck     {
1274c2c66affSColin Finck         if (_wcsnicmp(argv[j], L"/active:", 8) == 0)
1275c2c66affSColin Finck         {
1276c2c66affSColin Finck             p = &argv[i][8];
1277c2c66affSColin Finck             if (_wcsicmp(p, L"yes") == 0)
1278c2c66affSColin Finck             {
1279c2c66affSColin Finck                 pUserInfo->usri4_flags &= ~UF_ACCOUNTDISABLE;
1280c2c66affSColin Finck             }
1281c2c66affSColin Finck             else if (_wcsicmp(p, L"no") == 0)
1282c2c66affSColin Finck             {
1283c2c66affSColin Finck                 pUserInfo->usri4_flags |= UF_ACCOUNTDISABLE;
1284c2c66affSColin Finck             }
1285c2c66affSColin Finck             else
1286c2c66affSColin Finck             {
128729bf2097SEric Kohl                 PrintMessageStringV(3952, L"/ACTIVE");
1288c2c66affSColin Finck                 result = 1;
1289c2c66affSColin Finck                 goto done;
1290c2c66affSColin Finck             }
1291c2c66affSColin Finck         }
1292c2c66affSColin Finck         else if (_wcsnicmp(argv[j], L"/comment:", 9) == 0)
1293c2c66affSColin Finck         {
1294c2c66affSColin Finck             pUserInfo->usri4_comment = &argv[j][9];
1295c2c66affSColin Finck         }
1296c2c66affSColin Finck         else if (_wcsnicmp(argv[j], L"/countrycode:", 13) == 0)
1297c2c66affSColin Finck         {
1298c2c66affSColin Finck             p = &argv[i][13];
1299c2c66affSColin Finck             value = wcstoul(p, &endptr, 10);
1300c2c66affSColin Finck             if (*endptr != 0)
1301c2c66affSColin Finck             {
130229bf2097SEric Kohl                 PrintMessageStringV(3952, L"/COUNTRYCODE");
1303c2c66affSColin Finck                 result = 1;
1304c2c66affSColin Finck                 goto done;
1305c2c66affSColin Finck             }
1306c2c66affSColin Finck 
130708d30403SEric Kohl             /* Verify the country code */
130808d30403SEric Kohl             if (GetCountryFromCountryCode(value, 0, NULL))
1309c2c66affSColin Finck                 pUserInfo->usri4_country_code = value;
1310c2c66affSColin Finck         }
1311c2c66affSColin Finck         else if (_wcsnicmp(argv[j], L"/expires:", 9) == 0)
1312c2c66affSColin Finck         {
1313c2c66affSColin Finck             p = &argv[i][9];
1314c2c66affSColin Finck             if (_wcsicmp(p, L"never") == 0)
1315c2c66affSColin Finck             {
1316c2c66affSColin Finck                 pUserInfo->usri4_acct_expires = TIMEQ_FOREVER;
1317c2c66affSColin Finck             }
1318bf76e1bfSEric Kohl             else if (!ParseDate(p, &pUserInfo->usri4_acct_expires))
1319c2c66affSColin Finck             {
132029bf2097SEric Kohl                 PrintMessageStringV(3952, L"/EXPIRES");
1321bf76e1bfSEric Kohl                 result = 1;
1322bf76e1bfSEric Kohl                 goto done;
1323c2c66affSColin Finck             }
1324c2c66affSColin Finck         }
1325c2c66affSColin Finck         else if (_wcsnicmp(argv[j], L"/fullname:", 10) == 0)
1326c2c66affSColin Finck         {
1327c2c66affSColin Finck             pUserInfo->usri4_full_name = &argv[j][10];
1328c2c66affSColin Finck         }
1329c2c66affSColin Finck         else if (_wcsnicmp(argv[j], L"/homedir:", 9) == 0)
1330c2c66affSColin Finck         {
1331c2c66affSColin Finck             pUserInfo->usri4_home_dir = &argv[j][9];
1332c2c66affSColin Finck         }
1333c2c66affSColin Finck         else if (_wcsnicmp(argv[j], L"/passwordchg:", 13) == 0)
1334c2c66affSColin Finck         {
1335c2c66affSColin Finck             p = &argv[i][13];
1336c2c66affSColin Finck             if (_wcsicmp(p, L"yes") == 0)
1337c2c66affSColin Finck             {
1338c2c66affSColin Finck                 pUserInfo->usri4_flags &= ~UF_PASSWD_CANT_CHANGE;
1339c2c66affSColin Finck             }
1340c2c66affSColin Finck             else if (_wcsicmp(p, L"no") == 0)
1341c2c66affSColin Finck             {
1342c2c66affSColin Finck                 pUserInfo->usri4_flags |= UF_PASSWD_CANT_CHANGE;
1343c2c66affSColin Finck             }
1344c2c66affSColin Finck             else
1345c2c66affSColin Finck             {
134629bf2097SEric Kohl                 PrintMessageStringV(3952, L"/PASSWORDCHG");
1347c2c66affSColin Finck                 result = 1;
1348c2c66affSColin Finck                 goto done;
1349c2c66affSColin Finck             }
1350c2c66affSColin Finck         }
1351c2c66affSColin Finck         else if (_wcsnicmp(argv[j], L"/passwordreq:", 13) == 0)
1352c2c66affSColin Finck         {
1353c2c66affSColin Finck             p = &argv[i][13];
1354c2c66affSColin Finck             if (_wcsicmp(p, L"yes") == 0)
1355c2c66affSColin Finck             {
1356c2c66affSColin Finck                 pUserInfo->usri4_flags &= ~UF_PASSWD_NOTREQD;
1357c2c66affSColin Finck             }
1358c2c66affSColin Finck             else if (_wcsicmp(p, L"no") == 0)
1359c2c66affSColin Finck             {
1360c2c66affSColin Finck                 pUserInfo->usri4_flags |= UF_PASSWD_NOTREQD;
1361c2c66affSColin Finck             }
1362c2c66affSColin Finck             else
1363c2c66affSColin Finck             {
136429bf2097SEric Kohl                 PrintMessageStringV(3952, L"/PASSWORDREQ");
1365c2c66affSColin Finck                 result = 1;
1366c2c66affSColin Finck                 goto done;
1367c2c66affSColin Finck             }
1368c2c66affSColin Finck         }
1369c2c66affSColin Finck         else if (_wcsnicmp(argv[j], L"/profilepath:", 13) == 0)
1370c2c66affSColin Finck         {
1371c2c66affSColin Finck             pUserInfo->usri4_profile = &argv[j][13];
1372c2c66affSColin Finck         }
1373c2c66affSColin Finck         else if (_wcsnicmp(argv[j], L"/scriptpath:", 12) == 0)
1374c2c66affSColin Finck         {
1375c2c66affSColin Finck             pUserInfo->usri4_script_path = &argv[j][12];
1376c2c66affSColin Finck         }
1377c2c66affSColin Finck         else if (_wcsnicmp(argv[j], L"/times:", 7) == 0)
1378c2c66affSColin Finck         {
1379611e6d7dSEric Kohl             Status = ParseLogonHours(&argv[j][7],
1380611e6d7dSEric Kohl                                      &pLogonHours,
1381611e6d7dSEric Kohl                                      &dwUnitsPerWeek);
1382611e6d7dSEric Kohl             if (Status == ERROR_SUCCESS)
1383611e6d7dSEric Kohl             {
1384611e6d7dSEric Kohl                 pUserInfo->usri4_logon_hours = pLogonHours;
1385611e6d7dSEric Kohl                 pUserInfo->usri4_units_per_week = dwUnitsPerWeek;
1386611e6d7dSEric Kohl             }
1387611e6d7dSEric Kohl             else
1388611e6d7dSEric Kohl             {
1389611e6d7dSEric Kohl                 PrintMessageString(Status);
1390611e6d7dSEric Kohl                 goto done;
1391611e6d7dSEric Kohl             }
1392c2c66affSColin Finck         }
1393c2c66affSColin Finck         else if (_wcsnicmp(argv[j], L"/usercomment:", 13) == 0)
1394c2c66affSColin Finck         {
1395c2c66affSColin Finck             pUserInfo->usri4_usr_comment = &argv[j][13];
1396c2c66affSColin Finck         }
1397c2c66affSColin Finck         else if (_wcsnicmp(argv[j], L"/workstations:", 14) == 0)
1398c2c66affSColin Finck         {
1399add1be24SEric Kohl             p = &argv[i][14];
1400add1be24SEric Kohl             if (wcscmp(p, L"*") == 0 || wcscmp(p, L"") == 0)
1401add1be24SEric Kohl             {
1402add1be24SEric Kohl                 pUserInfo->usri4_workstations = NULL;
1403add1be24SEric Kohl             }
1404add1be24SEric Kohl             else
1405add1be24SEric Kohl             {
1406add1be24SEric Kohl                 Status = BuildWorkstationsList(&pWorkstations, p);
1407add1be24SEric Kohl                 if (Status == NERR_Success)
1408add1be24SEric Kohl                 {
1409add1be24SEric Kohl                     pUserInfo->usri4_workstations = pWorkstations;
1410add1be24SEric Kohl                 }
1411add1be24SEric Kohl                 else
1412add1be24SEric Kohl                 {
1413073607c2SMarat Nagayev                     PrintMessageString(TranslateAppMessage(Status));
1414add1be24SEric Kohl                     result = 1;
1415add1be24SEric Kohl                     goto done;
1416add1be24SEric Kohl                 }
1417add1be24SEric Kohl             }
1418c2c66affSColin Finck         }
1419c2c66affSColin Finck     }
1420c2c66affSColin Finck 
1421c2c66affSColin Finck     if (!bAdd && !bDelete)
1422c2c66affSColin Finck     {
1423c2c66affSColin Finck         /* Modify the user */
1424c2c66affSColin Finck         Status = NetUserSetInfo(NULL,
1425c2c66affSColin Finck                                 lpUserName,
1426c2c66affSColin Finck                                 4,
1427c2c66affSColin Finck                                 (LPBYTE)pUserInfo,
1428c2c66affSColin Finck                                 NULL);
1429c2c66affSColin Finck     }
1430073607c2SMarat Nagayev     else if (bAdd)
1431c2c66affSColin Finck     {
1432c2c66affSColin Finck         /* Add the user */
1433c2c66affSColin Finck         Status = NetUserAdd(NULL,
1434c2c66affSColin Finck                             4,
1435c2c66affSColin Finck                             (LPBYTE)pUserInfo,
1436c2c66affSColin Finck                             NULL);
1437c2c66affSColin Finck     }
1438073607c2SMarat Nagayev     else if (bDelete)
1439c2c66affSColin Finck     {
1440c2c66affSColin Finck         /* Delete the user */
1441c2c66affSColin Finck         Status = NetUserDel(NULL,
1442c2c66affSColin Finck                             lpUserName);
1443c2c66affSColin Finck     }
1444c2c66affSColin Finck 
1445073607c2SMarat Nagayev     PrintMessageString(TranslateAppMessage(Status));
1446073607c2SMarat Nagayev 
1447b4969dc0SEric Kohl     if (Status == NERR_Success &&
1448b4969dc0SEric Kohl         lpPassword != NULL &&
1449b4969dc0SEric Kohl         bRandomPassword == TRUE)
1450b4969dc0SEric Kohl     {
14515563525aSEric Kohl         PrintMessageStringV(3968, lpUserName, lpPassword);
1452b4969dc0SEric Kohl     }
1453b4969dc0SEric Kohl 
1454c2c66affSColin Finck done:
1455611e6d7dSEric Kohl     if (pLogonHours != NULL)
1456611e6d7dSEric Kohl         HeapFree(GetProcessHeap(), 0, pLogonHours);
1457611e6d7dSEric Kohl 
1458add1be24SEric Kohl     if (pWorkstations != NULL)
1459add1be24SEric Kohl         HeapFree(GetProcessHeap(), 0, pWorkstations);
1460add1be24SEric Kohl 
1461506bd64eSEric Kohl     if ((bPasswordAllocated == TRUE) && (lpPassword != NULL))
1462c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, lpPassword);
1463c2c66affSColin Finck 
1464c2c66affSColin Finck     if (!bAdd && !bDelete && pUserInfo != NULL)
1465c2c66affSColin Finck         NetApiBufferFree(pUserInfo);
1466c2c66affSColin Finck 
1467c2c66affSColin Finck     if (result != 0)
1468480cd1e6SEric Kohl     {
146929bf2097SEric Kohl         PrintMessageString(4381);
147029bf2097SEric Kohl         ConPuts(StdOut, L"\n");
14714e28e654SEric Kohl         PrintNetMessage(MSG_USER_SYNTAX);
1472480cd1e6SEric Kohl     }
1473c2c66affSColin Finck 
1474c2c66affSColin Finck     return result;
1475c2c66affSColin Finck }
1476c2c66affSColin Finck 
1477c2c66affSColin Finck /* EOF */
1478