1*c2c66affSColin Finck /*
2*c2c66affSColin Finck  * COPYRIGHT:       See COPYING in the top level directory
3*c2c66affSColin Finck  * PROJECT:         ReactOS net command
4*c2c66affSColin Finck  * FILE:            base/applications/network/net/cmdUser.c
5*c2c66affSColin Finck  * PURPOSE:
6*c2c66affSColin Finck  *
7*c2c66affSColin Finck  * PROGRAMMERS:     Eric Kohl
8*c2c66affSColin Finck  *                  Curtis Wilson
9*c2c66affSColin Finck  */
10*c2c66affSColin Finck 
11*c2c66affSColin Finck #include "net.h"
12*c2c66affSColin Finck 
13*c2c66affSColin Finck 
14*c2c66affSColin Finck static
15*c2c66affSColin Finck int
16*c2c66affSColin Finck CompareInfo(const void *a,
17*c2c66affSColin Finck             const void *b)
18*c2c66affSColin Finck {
19*c2c66affSColin Finck     return _wcsicmp(((PUSER_INFO_0)a)->usri0_name,
20*c2c66affSColin Finck                     ((PUSER_INFO_0)b)->usri0_name);
21*c2c66affSColin Finck }
22*c2c66affSColin Finck 
23*c2c66affSColin Finck 
24*c2c66affSColin Finck static
25*c2c66affSColin Finck NET_API_STATUS
26*c2c66affSColin Finck EnumerateUsers(VOID)
27*c2c66affSColin Finck {
28*c2c66affSColin Finck     PUSER_INFO_0 pBuffer = NULL;
29*c2c66affSColin Finck     PSERVER_INFO_100 pServer = NULL;
30*c2c66affSColin Finck     DWORD dwRead = 0, dwTotal = 0;
31*c2c66affSColin Finck     DWORD i;
32*c2c66affSColin Finck     DWORD_PTR ResumeHandle = 0;
33*c2c66affSColin Finck     NET_API_STATUS Status;
34*c2c66affSColin Finck 
35*c2c66affSColin Finck     Status = NetServerGetInfo(NULL,
36*c2c66affSColin Finck                               100,
37*c2c66affSColin Finck                               (LPBYTE*)&pServer);
38*c2c66affSColin Finck     if (Status != NERR_Success)
39*c2c66affSColin Finck         return Status;
40*c2c66affSColin Finck 
41*c2c66affSColin Finck     ConPuts(StdOut, L"\n");
42*c2c66affSColin Finck     ConResPrintf(StdOut, IDS_USER_ACCOUNTS, pServer->sv100_name);
43*c2c66affSColin Finck     ConPuts(StdOut, L"\n\n");
44*c2c66affSColin Finck     PrintPadding(L'-', 79);
45*c2c66affSColin Finck     ConPuts(StdOut, L"\n");
46*c2c66affSColin Finck 
47*c2c66affSColin Finck     NetApiBufferFree(pServer);
48*c2c66affSColin Finck 
49*c2c66affSColin Finck     do
50*c2c66affSColin Finck     {
51*c2c66affSColin Finck         Status = NetUserEnum(NULL,
52*c2c66affSColin Finck                              0,
53*c2c66affSColin Finck                              0,
54*c2c66affSColin Finck                              (LPBYTE*)&pBuffer,
55*c2c66affSColin Finck                              MAX_PREFERRED_LENGTH,
56*c2c66affSColin Finck                              &dwRead,
57*c2c66affSColin Finck                              &dwTotal,
58*c2c66affSColin Finck                              &ResumeHandle);
59*c2c66affSColin Finck         if ((Status != NERR_Success) && (Status != ERROR_MORE_DATA))
60*c2c66affSColin Finck             return Status;
61*c2c66affSColin Finck 
62*c2c66affSColin Finck         qsort(pBuffer,
63*c2c66affSColin Finck               dwRead,
64*c2c66affSColin Finck               sizeof(PUSER_INFO_0),
65*c2c66affSColin Finck               CompareInfo);
66*c2c66affSColin Finck 
67*c2c66affSColin Finck         for (i = 0; i < dwRead; i++)
68*c2c66affSColin Finck         {
69*c2c66affSColin Finck             if (pBuffer[i].usri0_name)
70*c2c66affSColin Finck                 ConPrintf(StdOut, L"%s\n", pBuffer[i].usri0_name);
71*c2c66affSColin Finck         }
72*c2c66affSColin Finck 
73*c2c66affSColin Finck         NetApiBufferFree(pBuffer);
74*c2c66affSColin Finck         pBuffer = NULL;
75*c2c66affSColin Finck     }
76*c2c66affSColin Finck     while (Status == ERROR_MORE_DATA);
77*c2c66affSColin Finck 
78*c2c66affSColin Finck     return NERR_Success;
79*c2c66affSColin Finck }
80*c2c66affSColin Finck 
81*c2c66affSColin Finck 
82*c2c66affSColin Finck static
83*c2c66affSColin Finck VOID
84*c2c66affSColin Finck PrintDateTime(DWORD dwSeconds)
85*c2c66affSColin Finck {
86*c2c66affSColin Finck     LARGE_INTEGER Time;
87*c2c66affSColin Finck     FILETIME FileTime;
88*c2c66affSColin Finck     SYSTEMTIME SystemTime;
89*c2c66affSColin Finck     WCHAR DateBuffer[80];
90*c2c66affSColin Finck     WCHAR TimeBuffer[80];
91*c2c66affSColin Finck 
92*c2c66affSColin Finck     RtlSecondsSince1970ToTime(dwSeconds, &Time);
93*c2c66affSColin Finck     FileTime.dwLowDateTime = Time.u.LowPart;
94*c2c66affSColin Finck     FileTime.dwHighDateTime = Time.u.HighPart;
95*c2c66affSColin Finck     FileTimeToLocalFileTime(&FileTime, &FileTime);
96*c2c66affSColin Finck     FileTimeToSystemTime(&FileTime, &SystemTime);
97*c2c66affSColin Finck 
98*c2c66affSColin Finck     GetDateFormatW(LOCALE_USER_DEFAULT,
99*c2c66affSColin Finck                    DATE_SHORTDATE,
100*c2c66affSColin Finck                    &SystemTime,
101*c2c66affSColin Finck                    NULL,
102*c2c66affSColin Finck                    DateBuffer,
103*c2c66affSColin Finck                    80);
104*c2c66affSColin Finck 
105*c2c66affSColin Finck     GetTimeFormatW(LOCALE_USER_DEFAULT,
106*c2c66affSColin Finck                    TIME_NOSECONDS,
107*c2c66affSColin Finck                    &SystemTime,
108*c2c66affSColin Finck                    NULL,
109*c2c66affSColin Finck                    TimeBuffer,
110*c2c66affSColin Finck                    80);
111*c2c66affSColin Finck 
112*c2c66affSColin Finck     ConPrintf(StdOut, L"%s %s", DateBuffer, TimeBuffer);
113*c2c66affSColin Finck }
114*c2c66affSColin Finck 
115*c2c66affSColin Finck 
116*c2c66affSColin Finck static
117*c2c66affSColin Finck DWORD
118*c2c66affSColin Finck GetTimeInSeconds(VOID)
119*c2c66affSColin Finck {
120*c2c66affSColin Finck     LARGE_INTEGER Time;
121*c2c66affSColin Finck     FILETIME FileTime;
122*c2c66affSColin Finck     DWORD dwSeconds;
123*c2c66affSColin Finck 
124*c2c66affSColin Finck     GetSystemTimeAsFileTime(&FileTime);
125*c2c66affSColin Finck     Time.u.LowPart = FileTime.dwLowDateTime;
126*c2c66affSColin Finck     Time.u.HighPart = FileTime.dwHighDateTime;
127*c2c66affSColin Finck     RtlTimeToSecondsSince1970(&Time, &dwSeconds);
128*c2c66affSColin Finck 
129*c2c66affSColin Finck     return dwSeconds;
130*c2c66affSColin Finck }
131*c2c66affSColin Finck 
132*c2c66affSColin Finck 
133*c2c66affSColin Finck static
134*c2c66affSColin Finck NET_API_STATUS
135*c2c66affSColin Finck DisplayUser(LPWSTR lpUserName)
136*c2c66affSColin Finck {
137*c2c66affSColin Finck     PUSER_MODALS_INFO_0 pUserModals = NULL;
138*c2c66affSColin Finck     PUSER_INFO_4 pUserInfo = NULL;
139*c2c66affSColin Finck     PLOCALGROUP_USERS_INFO_0 pLocalGroupInfo = NULL;
140*c2c66affSColin Finck     PGROUP_USERS_INFO_0 pGroupInfo = NULL;
141*c2c66affSColin Finck     DWORD dwLocalGroupRead, dwLocalGroupTotal;
142*c2c66affSColin Finck     DWORD dwGroupRead, dwGroupTotal;
143*c2c66affSColin Finck     DWORD dwLastSet;
144*c2c66affSColin Finck     DWORD i;
145*c2c66affSColin Finck     INT nPaddedLength = 29;
146*c2c66affSColin Finck     NET_API_STATUS Status;
147*c2c66affSColin Finck 
148*c2c66affSColin Finck     /* Modify the user */
149*c2c66affSColin Finck     Status = NetUserGetInfo(NULL,
150*c2c66affSColin Finck                             lpUserName,
151*c2c66affSColin Finck                             4,
152*c2c66affSColin Finck                             (LPBYTE*)&pUserInfo);
153*c2c66affSColin Finck     if (Status != NERR_Success)
154*c2c66affSColin Finck         return Status;
155*c2c66affSColin Finck 
156*c2c66affSColin Finck     Status = NetUserModalsGet(NULL,
157*c2c66affSColin Finck                               0,
158*c2c66affSColin Finck                               (LPBYTE*)&pUserModals);
159*c2c66affSColin Finck     if (Status != NERR_Success)
160*c2c66affSColin Finck         goto done;
161*c2c66affSColin Finck 
162*c2c66affSColin Finck     Status = NetUserGetLocalGroups(NULL,
163*c2c66affSColin Finck                                    lpUserName,
164*c2c66affSColin Finck                                    0,
165*c2c66affSColin Finck                                    0,
166*c2c66affSColin Finck                                    (LPBYTE*)&pLocalGroupInfo,
167*c2c66affSColin Finck                                    MAX_PREFERRED_LENGTH,
168*c2c66affSColin Finck                                    &dwLocalGroupRead,
169*c2c66affSColin Finck                                    &dwLocalGroupTotal);
170*c2c66affSColin Finck     if (Status != NERR_Success)
171*c2c66affSColin Finck         goto done;
172*c2c66affSColin Finck 
173*c2c66affSColin Finck     Status = NetUserGetGroups(NULL,
174*c2c66affSColin Finck                               lpUserName,
175*c2c66affSColin Finck                               0,
176*c2c66affSColin Finck                               (LPBYTE*)&pGroupInfo,
177*c2c66affSColin Finck                               MAX_PREFERRED_LENGTH,
178*c2c66affSColin Finck                               &dwGroupRead,
179*c2c66affSColin Finck                               &dwGroupTotal);
180*c2c66affSColin Finck     if (Status != NERR_Success)
181*c2c66affSColin Finck         goto done;
182*c2c66affSColin Finck 
183*c2c66affSColin Finck     PrintPaddedResourceString(IDS_USER_NAME, nPaddedLength);
184*c2c66affSColin Finck     ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_name);
185*c2c66affSColin Finck 
186*c2c66affSColin Finck     PrintPaddedResourceString(IDS_USER_FULL_NAME, nPaddedLength);
187*c2c66affSColin Finck     ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_full_name);
188*c2c66affSColin Finck 
189*c2c66affSColin Finck     PrintPaddedResourceString(IDS_USER_COMMENT, nPaddedLength);
190*c2c66affSColin Finck     ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_comment);
191*c2c66affSColin Finck 
192*c2c66affSColin Finck     PrintPaddedResourceString(IDS_USER_USER_COMMENT, nPaddedLength);
193*c2c66affSColin Finck     ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_usr_comment);
194*c2c66affSColin Finck 
195*c2c66affSColin Finck     PrintPaddedResourceString(IDS_USER_COUNTRY_CODE, nPaddedLength);
196*c2c66affSColin Finck     ConPrintf(StdOut, L"%03ld ()\n", pUserInfo->usri4_country_code);
197*c2c66affSColin Finck 
198*c2c66affSColin Finck     PrintPaddedResourceString(IDS_USER_ACCOUNT_ACTIVE, nPaddedLength);
199*c2c66affSColin Finck     if (pUserInfo->usri4_flags & UF_ACCOUNTDISABLE)
200*c2c66affSColin Finck         ConResPuts(StdOut, IDS_GENERIC_NO);
201*c2c66affSColin Finck     else if (pUserInfo->usri4_flags & UF_LOCKOUT)
202*c2c66affSColin Finck         ConResPuts(StdOut, IDS_GENERIC_LOCKED);
203*c2c66affSColin Finck     else
204*c2c66affSColin Finck         ConResPuts(StdOut, IDS_GENERIC_YES);
205*c2c66affSColin Finck     ConPuts(StdOut, L"\n");
206*c2c66affSColin Finck 
207*c2c66affSColin Finck     PrintPaddedResourceString(IDS_USER_ACCOUNT_EXPIRES, nPaddedLength);
208*c2c66affSColin Finck     if (pUserInfo->usri4_acct_expires == TIMEQ_FOREVER)
209*c2c66affSColin Finck         ConResPuts(StdOut, IDS_GENERIC_NEVER);
210*c2c66affSColin Finck     else
211*c2c66affSColin Finck         PrintDateTime(pUserInfo->usri4_acct_expires);
212*c2c66affSColin Finck     ConPuts(StdOut, L"\n\n");
213*c2c66affSColin Finck 
214*c2c66affSColin Finck     PrintPaddedResourceString(IDS_USER_PW_LAST_SET, nPaddedLength);
215*c2c66affSColin Finck     dwLastSet = GetTimeInSeconds() - pUserInfo->usri4_password_age;
216*c2c66affSColin Finck     PrintDateTime(dwLastSet);
217*c2c66affSColin Finck 
218*c2c66affSColin Finck     PrintPaddedResourceString(IDS_USER_PW_EXPIRES, nPaddedLength);
219*c2c66affSColin Finck     if ((pUserInfo->usri4_flags & UF_DONT_EXPIRE_PASSWD) || pUserModals->usrmod0_max_passwd_age == TIMEQ_FOREVER)
220*c2c66affSColin Finck         ConResPuts(StdOut, IDS_GENERIC_NEVER);
221*c2c66affSColin Finck     else
222*c2c66affSColin Finck         PrintDateTime(dwLastSet + pUserModals->usrmod0_max_passwd_age);
223*c2c66affSColin Finck     ConPuts(StdOut, L"\n");
224*c2c66affSColin Finck 
225*c2c66affSColin Finck     PrintPaddedResourceString(IDS_USER_PW_CHANGEABLE, nPaddedLength);
226*c2c66affSColin Finck     PrintDateTime(dwLastSet + pUserModals->usrmod0_min_passwd_age);
227*c2c66affSColin Finck 
228*c2c66affSColin Finck     PrintPaddedResourceString(IDS_USER_PW_REQUIRED, nPaddedLength);
229*c2c66affSColin Finck     ConResPuts(StdOut, (pUserInfo->usri4_flags & UF_PASSWD_NOTREQD) ? IDS_GENERIC_NO : IDS_GENERIC_YES);
230*c2c66affSColin Finck     ConPuts(StdOut, L"\n");
231*c2c66affSColin Finck 
232*c2c66affSColin Finck     PrintPaddedResourceString(IDS_USER_CHANGE_PW, nPaddedLength);
233*c2c66affSColin Finck     ConResPuts(StdOut, (pUserInfo->usri4_flags & UF_PASSWD_CANT_CHANGE) ? IDS_GENERIC_NO : IDS_GENERIC_YES);
234*c2c66affSColin Finck     ConPuts(StdOut, L"\n\n");
235*c2c66affSColin Finck 
236*c2c66affSColin Finck     PrintPaddedResourceString(IDS_USER_WORKSTATIONS, nPaddedLength);
237*c2c66affSColin Finck     if (pUserInfo->usri4_workstations == NULL || wcslen(pUserInfo->usri4_workstations) == 0)
238*c2c66affSColin Finck         ConResPuts(StdOut, IDS_GENERIC_ALL);
239*c2c66affSColin Finck     else
240*c2c66affSColin Finck         ConPrintf(StdOut, L"%s", pUserInfo->usri4_workstations);
241*c2c66affSColin Finck     ConPuts(StdOut, L"\n");
242*c2c66affSColin Finck 
243*c2c66affSColin Finck     PrintPaddedResourceString(IDS_USER_LOGON_SCRIPT, nPaddedLength);
244*c2c66affSColin Finck     ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_script_path);
245*c2c66affSColin Finck 
246*c2c66affSColin Finck     PrintPaddedResourceString(IDS_USER_PROFILE, nPaddedLength);
247*c2c66affSColin Finck     ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_profile);
248*c2c66affSColin Finck 
249*c2c66affSColin Finck     PrintPaddedResourceString(IDS_USER_HOME_DIR, nPaddedLength);
250*c2c66affSColin Finck     ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_home_dir);
251*c2c66affSColin Finck 
252*c2c66affSColin Finck     PrintPaddedResourceString(IDS_USER_LAST_LOGON, nPaddedLength);
253*c2c66affSColin Finck     if (pUserInfo->usri4_last_logon == 0)
254*c2c66affSColin Finck         ConResPuts(StdOut, IDS_GENERIC_NEVER);
255*c2c66affSColin Finck     else
256*c2c66affSColin Finck         PrintDateTime(pUserInfo->usri4_last_logon);
257*c2c66affSColin Finck     ConPuts(StdOut, L"\n\n");
258*c2c66affSColin Finck 
259*c2c66affSColin Finck     PrintPaddedResourceString(IDS_USER_LOGON_HOURS, nPaddedLength);
260*c2c66affSColin Finck     if (pUserInfo->usri4_logon_hours == NULL)
261*c2c66affSColin Finck         ConResPuts(StdOut, IDS_GENERIC_ALL);
262*c2c66affSColin Finck     ConPuts(StdOut, L"\n\n");
263*c2c66affSColin Finck 
264*c2c66affSColin Finck     ConPuts(StdOut, L"\n");
265*c2c66affSColin Finck     PrintPaddedResourceString(IDS_USER_LOCAL_GROUPS, nPaddedLength);
266*c2c66affSColin Finck     if (dwLocalGroupTotal != 0 && pLocalGroupInfo != NULL)
267*c2c66affSColin Finck     {
268*c2c66affSColin Finck         for (i = 0; i < dwLocalGroupTotal; i++)
269*c2c66affSColin Finck         {
270*c2c66affSColin Finck             if (i != 0)
271*c2c66affSColin Finck                 PrintPadding(L' ', nPaddedLength);
272*c2c66affSColin Finck             ConPrintf(StdOut, L"*%s\n", pLocalGroupInfo[i].lgrui0_name);
273*c2c66affSColin Finck         }
274*c2c66affSColin Finck     }
275*c2c66affSColin Finck     else
276*c2c66affSColin Finck     {
277*c2c66affSColin Finck         ConPuts(StdOut, L"\n");
278*c2c66affSColin Finck     }
279*c2c66affSColin Finck 
280*c2c66affSColin Finck     PrintPaddedResourceString(IDS_USER_GLOBAL_GROUPS, nPaddedLength);
281*c2c66affSColin Finck     if (dwGroupTotal != 0 && pGroupInfo != NULL)
282*c2c66affSColin Finck     {
283*c2c66affSColin Finck         for (i = 0; i < dwGroupTotal; i++)
284*c2c66affSColin Finck         {
285*c2c66affSColin Finck             if (i != 0)
286*c2c66affSColin Finck                 PrintPadding(L' ', nPaddedLength);
287*c2c66affSColin Finck             ConPrintf(StdOut, L"*%s\n", pGroupInfo[i].grui0_name);
288*c2c66affSColin Finck         }
289*c2c66affSColin Finck     }
290*c2c66affSColin Finck     else
291*c2c66affSColin Finck     {
292*c2c66affSColin Finck         ConPuts(StdOut, L"\n");
293*c2c66affSColin Finck     }
294*c2c66affSColin Finck 
295*c2c66affSColin Finck done:
296*c2c66affSColin Finck     if (pGroupInfo != NULL)
297*c2c66affSColin Finck         NetApiBufferFree(pGroupInfo);
298*c2c66affSColin Finck 
299*c2c66affSColin Finck     if (pLocalGroupInfo != NULL)
300*c2c66affSColin Finck         NetApiBufferFree(pLocalGroupInfo);
301*c2c66affSColin Finck 
302*c2c66affSColin Finck     if (pUserModals != NULL)
303*c2c66affSColin Finck         NetApiBufferFree(pUserModals);
304*c2c66affSColin Finck 
305*c2c66affSColin Finck     if (pUserInfo != NULL)
306*c2c66affSColin Finck         NetApiBufferFree(pUserInfo);
307*c2c66affSColin Finck 
308*c2c66affSColin Finck     return NERR_Success;
309*c2c66affSColin Finck }
310*c2c66affSColin Finck 
311*c2c66affSColin Finck 
312*c2c66affSColin Finck static
313*c2c66affSColin Finck VOID
314*c2c66affSColin Finck ReadPassword(
315*c2c66affSColin Finck     LPWSTR *lpPassword,
316*c2c66affSColin Finck     LPBOOL lpAllocated)
317*c2c66affSColin Finck {
318*c2c66affSColin Finck     WCHAR szPassword1[PWLEN + 1];
319*c2c66affSColin Finck     WCHAR szPassword2[PWLEN + 1];
320*c2c66affSColin Finck     LPWSTR ptr;
321*c2c66affSColin Finck 
322*c2c66affSColin Finck     *lpAllocated = FALSE;
323*c2c66affSColin Finck 
324*c2c66affSColin Finck     while (TRUE)
325*c2c66affSColin Finck     {
326*c2c66affSColin Finck         ConResPuts(StdOut, IDS_USER_ENTER_PASSWORD1);
327*c2c66affSColin Finck         ReadFromConsole(szPassword1, PWLEN + 1, FALSE);
328*c2c66affSColin Finck         ConPuts(StdOut, L"\n");
329*c2c66affSColin Finck 
330*c2c66affSColin Finck         ConResPuts(StdOut, IDS_USER_ENTER_PASSWORD2);
331*c2c66affSColin Finck         ReadFromConsole(szPassword2, PWLEN + 1, FALSE);
332*c2c66affSColin Finck         ConPuts(StdOut, L"\n");
333*c2c66affSColin Finck 
334*c2c66affSColin Finck         if (wcslen(szPassword1) == wcslen(szPassword2) &&
335*c2c66affSColin Finck             wcscmp(szPassword1, szPassword2) == 0)
336*c2c66affSColin Finck         {
337*c2c66affSColin Finck             ptr = HeapAlloc(GetProcessHeap(),
338*c2c66affSColin Finck                             0,
339*c2c66affSColin Finck                             (wcslen(szPassword1) + 1) * sizeof(WCHAR));
340*c2c66affSColin Finck             if (ptr != NULL)
341*c2c66affSColin Finck             {
342*c2c66affSColin Finck                 wcscpy(ptr, szPassword1);
343*c2c66affSColin Finck                 *lpPassword = ptr;
344*c2c66affSColin Finck                 *lpAllocated = TRUE;
345*c2c66affSColin Finck                 return;
346*c2c66affSColin Finck             }
347*c2c66affSColin Finck         }
348*c2c66affSColin Finck         else
349*c2c66affSColin Finck         {
350*c2c66affSColin Finck             ConPuts(StdOut, L"\n");
351*c2c66affSColin Finck             ConResPuts(StdOut, IDS_USER_NO_PASSWORD_MATCH);
352*c2c66affSColin Finck             ConPuts(StdOut, L"\n");
353*c2c66affSColin Finck             *lpPassword = NULL;
354*c2c66affSColin Finck         }
355*c2c66affSColin Finck     }
356*c2c66affSColin Finck }
357*c2c66affSColin Finck 
358*c2c66affSColin Finck 
359*c2c66affSColin Finck INT
360*c2c66affSColin Finck cmdUser(
361*c2c66affSColin Finck     INT argc,
362*c2c66affSColin Finck     WCHAR **argv)
363*c2c66affSColin Finck {
364*c2c66affSColin Finck     INT i, j;
365*c2c66affSColin Finck     INT result = 0;
366*c2c66affSColin Finck     BOOL bAdd = FALSE;
367*c2c66affSColin Finck     BOOL bDelete = FALSE;
368*c2c66affSColin Finck #if 0
369*c2c66affSColin Finck     BOOL bDomain = FALSE;
370*c2c66affSColin Finck #endif
371*c2c66affSColin Finck     LPWSTR lpUserName = NULL;
372*c2c66affSColin Finck     LPWSTR lpPassword = NULL;
373*c2c66affSColin Finck     PUSER_INFO_4 pUserInfo = NULL;
374*c2c66affSColin Finck     USER_INFO_4 UserInfo;
375*c2c66affSColin Finck     LPWSTR p;
376*c2c66affSColin Finck     LPWSTR endptr;
377*c2c66affSColin Finck     DWORD value;
378*c2c66affSColin Finck     BOOL bPasswordAllocated = FALSE;
379*c2c66affSColin Finck     NET_API_STATUS Status;
380*c2c66affSColin Finck 
381*c2c66affSColin Finck     if (argc == 2)
382*c2c66affSColin Finck     {
383*c2c66affSColin Finck         Status = EnumerateUsers();
384*c2c66affSColin Finck         ConPrintf(StdOut, L"Status: %lu\n", Status);
385*c2c66affSColin Finck         return 0;
386*c2c66affSColin Finck     }
387*c2c66affSColin Finck     else if (argc == 3)
388*c2c66affSColin Finck     {
389*c2c66affSColin Finck         Status = DisplayUser(argv[2]);
390*c2c66affSColin Finck         ConPrintf(StdOut, L"Status: %lu\n", Status);
391*c2c66affSColin Finck         return 0;
392*c2c66affSColin Finck     }
393*c2c66affSColin Finck 
394*c2c66affSColin Finck     i = 2;
395*c2c66affSColin Finck     if (argv[i][0] != L'/')
396*c2c66affSColin Finck     {
397*c2c66affSColin Finck         lpUserName = argv[i];
398*c2c66affSColin Finck //        ConPrintf(StdOut, L"User: %s\n", lpUserName);
399*c2c66affSColin Finck         i++;
400*c2c66affSColin Finck     }
401*c2c66affSColin Finck 
402*c2c66affSColin Finck     if (argv[i][0] != L'/')
403*c2c66affSColin Finck     {
404*c2c66affSColin Finck         lpPassword = argv[i];
405*c2c66affSColin Finck //        ConPrintf(StdOut, L"Password: %s\n", lpPassword);
406*c2c66affSColin Finck         i++;
407*c2c66affSColin Finck     }
408*c2c66affSColin Finck 
409*c2c66affSColin Finck     for (j = i; j < argc; j++)
410*c2c66affSColin Finck     {
411*c2c66affSColin Finck         if (_wcsicmp(argv[j], L"/help") == 0)
412*c2c66affSColin Finck         {
413*c2c66affSColin Finck             ConResPuts(StdOut, IDS_USER_HELP);
414*c2c66affSColin Finck             return 0;
415*c2c66affSColin Finck         }
416*c2c66affSColin Finck         else if (_wcsicmp(argv[j], L"/add") == 0)
417*c2c66affSColin Finck         {
418*c2c66affSColin Finck             bAdd = TRUE;
419*c2c66affSColin Finck         }
420*c2c66affSColin Finck         else if (_wcsicmp(argv[j], L"/delete") == 0)
421*c2c66affSColin Finck         {
422*c2c66affSColin Finck             bDelete = TRUE;
423*c2c66affSColin Finck         }
424*c2c66affSColin Finck         else if (_wcsicmp(argv[j], L"/domain") == 0)
425*c2c66affSColin Finck         {
426*c2c66affSColin Finck             ConResPrintf(StdErr, IDS_ERROR_OPTION_NOT_SUPPORTED, L"/DOMAIN");
427*c2c66affSColin Finck #if 0
428*c2c66affSColin Finck             bDomain = TRUE;
429*c2c66affSColin Finck #endif
430*c2c66affSColin Finck         }
431*c2c66affSColin Finck     }
432*c2c66affSColin Finck 
433*c2c66affSColin Finck     if (bAdd && bDelete)
434*c2c66affSColin Finck     {
435*c2c66affSColin Finck         result = 1;
436*c2c66affSColin Finck         goto done;
437*c2c66affSColin Finck     }
438*c2c66affSColin Finck 
439*c2c66affSColin Finck     /* Interactive password input */
440*c2c66affSColin Finck     if (lpPassword != NULL && wcscmp(lpPassword, L"*") == 0)
441*c2c66affSColin Finck     {
442*c2c66affSColin Finck         ReadPassword(&lpPassword,
443*c2c66affSColin Finck                      &bPasswordAllocated);
444*c2c66affSColin Finck     }
445*c2c66affSColin Finck 
446*c2c66affSColin Finck     if (!bAdd && !bDelete)
447*c2c66affSColin Finck     {
448*c2c66affSColin Finck         /* Modify the user */
449*c2c66affSColin Finck         Status = NetUserGetInfo(NULL,
450*c2c66affSColin Finck                                 lpUserName,
451*c2c66affSColin Finck                                 4,
452*c2c66affSColin Finck                                 (LPBYTE*)&pUserInfo);
453*c2c66affSColin Finck         if (Status != NERR_Success)
454*c2c66affSColin Finck         {
455*c2c66affSColin Finck             ConPrintf(StdOut, L"Status: %lu\n", Status);
456*c2c66affSColin Finck             result = 1;
457*c2c66affSColin Finck             goto done;
458*c2c66affSColin Finck         }
459*c2c66affSColin Finck     }
460*c2c66affSColin Finck     else if (bAdd && !bDelete)
461*c2c66affSColin Finck     {
462*c2c66affSColin Finck         /* Add the user */
463*c2c66affSColin Finck         ZeroMemory(&UserInfo, sizeof(USER_INFO_4));
464*c2c66affSColin Finck 
465*c2c66affSColin Finck         UserInfo.usri4_name = lpUserName;
466*c2c66affSColin Finck         UserInfo.usri4_password = lpPassword;
467*c2c66affSColin Finck         UserInfo.usri4_flags = UF_SCRIPT | UF_NORMAL_ACCOUNT;
468*c2c66affSColin Finck 
469*c2c66affSColin Finck         pUserInfo = &UserInfo;
470*c2c66affSColin Finck     }
471*c2c66affSColin Finck 
472*c2c66affSColin Finck     for (j = i; j < argc; j++)
473*c2c66affSColin Finck     {
474*c2c66affSColin Finck         if (_wcsnicmp(argv[j], L"/active:", 8) == 0)
475*c2c66affSColin Finck         {
476*c2c66affSColin Finck             p = &argv[i][8];
477*c2c66affSColin Finck             if (_wcsicmp(p, L"yes") == 0)
478*c2c66affSColin Finck             {
479*c2c66affSColin Finck                 pUserInfo->usri4_flags &= ~UF_ACCOUNTDISABLE;
480*c2c66affSColin Finck             }
481*c2c66affSColin Finck             else if (_wcsicmp(p, L"no") == 0)
482*c2c66affSColin Finck             {
483*c2c66affSColin Finck                 pUserInfo->usri4_flags |= UF_ACCOUNTDISABLE;
484*c2c66affSColin Finck             }
485*c2c66affSColin Finck             else
486*c2c66affSColin Finck             {
487*c2c66affSColin Finck                 ConResPrintf(StdErr, IDS_ERROR_INVALID_OPTION_VALUE, L"/ACTIVE");
488*c2c66affSColin Finck                 result = 1;
489*c2c66affSColin Finck                 goto done;
490*c2c66affSColin Finck             }
491*c2c66affSColin Finck         }
492*c2c66affSColin Finck         else if (_wcsnicmp(argv[j], L"/comment:", 9) == 0)
493*c2c66affSColin Finck         {
494*c2c66affSColin Finck             pUserInfo->usri4_comment = &argv[j][9];
495*c2c66affSColin Finck         }
496*c2c66affSColin Finck         else if (_wcsnicmp(argv[j], L"/countrycode:", 13) == 0)
497*c2c66affSColin Finck         {
498*c2c66affSColin Finck             p = &argv[i][13];
499*c2c66affSColin Finck             value = wcstoul(p, &endptr, 10);
500*c2c66affSColin Finck             if (*endptr != 0)
501*c2c66affSColin Finck             {
502*c2c66affSColin Finck                 ConResPrintf(StdErr, IDS_ERROR_INVALID_OPTION_VALUE, L"/COUNTRYCODE");
503*c2c66affSColin Finck                 result = 1;
504*c2c66affSColin Finck                 goto done;
505*c2c66affSColin Finck             }
506*c2c66affSColin Finck 
507*c2c66affSColin Finck             /* FIXME: verify the country code */
508*c2c66affSColin Finck 
509*c2c66affSColin Finck             pUserInfo->usri4_country_code = value;
510*c2c66affSColin Finck         }
511*c2c66affSColin Finck         else if (_wcsnicmp(argv[j], L"/expires:", 9) == 0)
512*c2c66affSColin Finck         {
513*c2c66affSColin Finck             p = &argv[i][9];
514*c2c66affSColin Finck             if (_wcsicmp(p, L"never") == 0)
515*c2c66affSColin Finck             {
516*c2c66affSColin Finck                 pUserInfo->usri4_acct_expires = TIMEQ_FOREVER;
517*c2c66affSColin Finck             }
518*c2c66affSColin Finck             else
519*c2c66affSColin Finck             {
520*c2c66affSColin Finck                 /* FIXME: Parse the date */
521*c2c66affSColin Finck                 ConResPrintf(StdErr, IDS_ERROR_OPTION_NOT_SUPPORTED, L"/EXPIRES");
522*c2c66affSColin Finck             }
523*c2c66affSColin Finck         }
524*c2c66affSColin Finck         else if (_wcsnicmp(argv[j], L"/fullname:", 10) == 0)
525*c2c66affSColin Finck         {
526*c2c66affSColin Finck             pUserInfo->usri4_full_name = &argv[j][10];
527*c2c66affSColin Finck         }
528*c2c66affSColin Finck         else if (_wcsnicmp(argv[j], L"/homedir:", 9) == 0)
529*c2c66affSColin Finck         {
530*c2c66affSColin Finck             pUserInfo->usri4_home_dir = &argv[j][9];
531*c2c66affSColin Finck         }
532*c2c66affSColin Finck         else if (_wcsnicmp(argv[j], L"/passwordchg:", 13) == 0)
533*c2c66affSColin Finck         {
534*c2c66affSColin Finck             p = &argv[i][13];
535*c2c66affSColin Finck             if (_wcsicmp(p, L"yes") == 0)
536*c2c66affSColin Finck             {
537*c2c66affSColin Finck                 pUserInfo->usri4_flags &= ~UF_PASSWD_CANT_CHANGE;
538*c2c66affSColin Finck             }
539*c2c66affSColin Finck             else if (_wcsicmp(p, L"no") == 0)
540*c2c66affSColin Finck             {
541*c2c66affSColin Finck                 pUserInfo->usri4_flags |= UF_PASSWD_CANT_CHANGE;
542*c2c66affSColin Finck             }
543*c2c66affSColin Finck             else
544*c2c66affSColin Finck             {
545*c2c66affSColin Finck                 ConResPrintf(StdErr, IDS_ERROR_INVALID_OPTION_VALUE, L"/PASSWORDCHG");
546*c2c66affSColin Finck                 result = 1;
547*c2c66affSColin Finck                 goto done;
548*c2c66affSColin Finck             }
549*c2c66affSColin Finck         }
550*c2c66affSColin Finck         else if (_wcsnicmp(argv[j], L"/passwordreq:", 13) == 0)
551*c2c66affSColin Finck         {
552*c2c66affSColin Finck             p = &argv[i][13];
553*c2c66affSColin Finck             if (_wcsicmp(p, L"yes") == 0)
554*c2c66affSColin Finck             {
555*c2c66affSColin Finck                 pUserInfo->usri4_flags &= ~UF_PASSWD_NOTREQD;
556*c2c66affSColin Finck             }
557*c2c66affSColin Finck             else if (_wcsicmp(p, L"no") == 0)
558*c2c66affSColin Finck             {
559*c2c66affSColin Finck                 pUserInfo->usri4_flags |= UF_PASSWD_NOTREQD;
560*c2c66affSColin Finck             }
561*c2c66affSColin Finck             else
562*c2c66affSColin Finck             {
563*c2c66affSColin Finck                 ConResPrintf(StdErr, IDS_ERROR_INVALID_OPTION_VALUE, L"/PASSWORDREQ");
564*c2c66affSColin Finck                 result = 1;
565*c2c66affSColin Finck                 goto done;
566*c2c66affSColin Finck             }
567*c2c66affSColin Finck         }
568*c2c66affSColin Finck         else if (_wcsnicmp(argv[j], L"/profilepath:", 13) == 0)
569*c2c66affSColin Finck         {
570*c2c66affSColin Finck             pUserInfo->usri4_profile = &argv[j][13];
571*c2c66affSColin Finck         }
572*c2c66affSColin Finck         else if (_wcsnicmp(argv[j], L"/scriptpath:", 12) == 0)
573*c2c66affSColin Finck         {
574*c2c66affSColin Finck             pUserInfo->usri4_script_path = &argv[j][12];
575*c2c66affSColin Finck         }
576*c2c66affSColin Finck         else if (_wcsnicmp(argv[j], L"/times:", 7) == 0)
577*c2c66affSColin Finck         {
578*c2c66affSColin Finck             /* FIXME */
579*c2c66affSColin Finck             ConResPrintf(StdErr, IDS_ERROR_OPTION_NOT_SUPPORTED, L"/TIMES");
580*c2c66affSColin Finck         }
581*c2c66affSColin Finck         else if (_wcsnicmp(argv[j], L"/usercomment:", 13) == 0)
582*c2c66affSColin Finck         {
583*c2c66affSColin Finck             pUserInfo->usri4_usr_comment = &argv[j][13];
584*c2c66affSColin Finck         }
585*c2c66affSColin Finck         else if (_wcsnicmp(argv[j], L"/workstations:", 14) == 0)
586*c2c66affSColin Finck         {
587*c2c66affSColin Finck             /* FIXME */
588*c2c66affSColin Finck             ConResPrintf(StdErr, IDS_ERROR_OPTION_NOT_SUPPORTED, L"/WORKSTATIONS");
589*c2c66affSColin Finck         }
590*c2c66affSColin Finck     }
591*c2c66affSColin Finck 
592*c2c66affSColin Finck     if (!bAdd && !bDelete)
593*c2c66affSColin Finck     {
594*c2c66affSColin Finck         /* Modify the user */
595*c2c66affSColin Finck         Status = NetUserSetInfo(NULL,
596*c2c66affSColin Finck                                 lpUserName,
597*c2c66affSColin Finck                                 4,
598*c2c66affSColin Finck                                 (LPBYTE)pUserInfo,
599*c2c66affSColin Finck                                 NULL);
600*c2c66affSColin Finck         ConPrintf(StdOut, L"Status: %lu\n", Status);
601*c2c66affSColin Finck     }
602*c2c66affSColin Finck     else if (bAdd && !bDelete)
603*c2c66affSColin Finck     {
604*c2c66affSColin Finck         /* Add the user */
605*c2c66affSColin Finck         Status = NetUserAdd(NULL,
606*c2c66affSColin Finck                             4,
607*c2c66affSColin Finck                             (LPBYTE)pUserInfo,
608*c2c66affSColin Finck                             NULL);
609*c2c66affSColin Finck         ConPrintf(StdOut, L"Status: %lu\n", Status);
610*c2c66affSColin Finck     }
611*c2c66affSColin Finck     else if (!bAdd && bDelete)
612*c2c66affSColin Finck     {
613*c2c66affSColin Finck         /* Delete the user */
614*c2c66affSColin Finck         Status = NetUserDel(NULL,
615*c2c66affSColin Finck                             lpUserName);
616*c2c66affSColin Finck         ConPrintf(StdOut, L"Status: %lu\n", Status);
617*c2c66affSColin Finck     }
618*c2c66affSColin Finck 
619*c2c66affSColin Finck done:
620*c2c66affSColin Finck     if ((bPasswordAllocated != FALSE) && (lpPassword != NULL))
621*c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, lpPassword);
622*c2c66affSColin Finck 
623*c2c66affSColin Finck     if (!bAdd && !bDelete && pUserInfo != NULL)
624*c2c66affSColin Finck         NetApiBufferFree(pUserInfo);
625*c2c66affSColin Finck 
626*c2c66affSColin Finck     if (result != 0)
627*c2c66affSColin Finck         ConResPuts(StdOut, IDS_USER_SYNTAX);
628*c2c66affSColin Finck 
629*c2c66affSColin Finck     return result;
630*c2c66affSColin Finck }
631*c2c66affSColin Finck 
632*c2c66affSColin Finck /* EOF */
633