c9d07c4c89f2d7c7a38a5f2eacb06f01e307928d
[reactos.git] / reactos / base / applications / network / net / cmdUser.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS net command
4 * FILE:
5 * PURPOSE:
6 *
7 * PROGRAMMERS: Eric Kohl
8 */
9
10 #include "net.h"
11
12
13 static
14 int
15 CompareInfo(const void *a,
16 const void *b)
17 {
18 return _wcsicmp(((PUSER_INFO_0)a)->usri0_name,
19 ((PUSER_INFO_0)b)->usri0_name);
20 }
21
22
23 static
24 NET_API_STATUS
25 EnumerateUsers(VOID)
26 {
27 PUSER_INFO_0 pBuffer = NULL;
28 PSERVER_INFO_100 pServer = NULL;
29 DWORD dwRead = 0, dwTotal = 0;
30 DWORD i;
31 DWORD_PTR ResumeHandle = 0;
32 NET_API_STATUS Status;
33
34 Status = NetServerGetInfo(NULL,
35 100,
36 (LPBYTE*)&pServer);
37 if (Status != NERR_Success)
38 return Status;
39
40 PrintToConsole(L"\nUser accounts for \\\\%s\n\n", pServer->sv100_name);
41
42 NetApiBufferFree(pServer);
43
44 PrintToConsole(L"------------------------------------------\n");
45
46 Status = NetUserEnum(NULL,
47 0,
48 0,
49 (LPBYTE*)&pBuffer,
50 MAX_PREFERRED_LENGTH,
51 &dwRead,
52 &dwTotal,
53 &ResumeHandle);
54 if (Status != NERR_Success)
55 return Status;
56
57 qsort(pBuffer,
58 dwRead,
59 sizeof(PUSER_INFO_0),
60 CompareInfo);
61
62 // printf("dwRead: %lu dwTotal: %lu\n", dwRead, dwTotal);
63 for (i = 0; i < dwRead; i++)
64 {
65 // printf("%p\n", pBuffer[i].lgrpi0_name);
66 if (pBuffer[i].usri0_name)
67 PrintToConsole(L"%s\n", pBuffer[i].usri0_name);
68 }
69
70 NetApiBufferFree(pBuffer);
71
72 return NERR_Success;
73 }
74
75
76 static
77 VOID
78 PrintDateTime(DWORD dwSeconds)
79 {
80 LARGE_INTEGER Time;
81 FILETIME FileTime;
82 SYSTEMTIME SystemTime;
83 WCHAR DateBuffer[80];
84 WCHAR TimeBuffer[80];
85
86 RtlSecondsSince1970ToTime(dwSeconds, &Time);
87 FileTime.dwLowDateTime = Time.u.LowPart;
88 FileTime.dwHighDateTime = Time.u.HighPart;
89 FileTimeToLocalFileTime(&FileTime, &FileTime);
90 FileTimeToSystemTime(&FileTime, &SystemTime);
91
92 GetDateFormatW(LOCALE_USER_DEFAULT,
93 DATE_SHORTDATE,
94 &SystemTime,
95 NULL,
96 DateBuffer,
97 80);
98
99 GetTimeFormatW(LOCALE_USER_DEFAULT,
100 TIME_NOSECONDS,
101 &SystemTime,
102 NULL,
103 TimeBuffer,
104 80);
105
106 PrintToConsole(L"%s %s\n", DateBuffer, TimeBuffer);
107 }
108
109
110 static
111 DWORD
112 GetTimeInSeconds(VOID)
113 {
114 LARGE_INTEGER Time;
115 FILETIME FileTime;
116 DWORD dwSeconds;
117
118 GetSystemTimeAsFileTime(&FileTime);
119 Time.u.LowPart = FileTime.dwLowDateTime;
120 Time.u.HighPart = FileTime.dwHighDateTime;
121 RtlTimeToSecondsSince1970(&Time, &dwSeconds);
122
123 return dwSeconds;
124 }
125
126
127 static
128 NET_API_STATUS
129 DisplayUser(LPWSTR lpUserName)
130 {
131 PUSER_MODALS_INFO_0 pUserModals = NULL;
132 PUSER_INFO_4 pUserInfo = NULL;
133 PLOCALGROUP_USERS_INFO_0 pLocalGroupInfo = NULL;
134 PGROUP_USERS_INFO_0 pGroupInfo = NULL;
135 DWORD dwLocalGroupRead, dwLocalGroupTotal;
136 DWORD dwGroupRead, dwGroupTotal;
137 DWORD dwLastSet;
138 DWORD i;
139 NET_API_STATUS Status;
140
141 /* Modify the user */
142 Status = NetUserGetInfo(NULL,
143 lpUserName,
144 4,
145 (LPBYTE*)&pUserInfo);
146 if (Status != NERR_Success)
147 return Status;
148
149 Status = NetUserModalsGet(NULL,
150 0,
151 (LPBYTE*)&pUserModals);
152 if (Status != NERR_Success)
153 goto done;
154
155 Status = NetUserGetLocalGroups(NULL,
156 lpUserName,
157 0,
158 0,
159 (LPBYTE*)&pLocalGroupInfo,
160 MAX_PREFERRED_LENGTH,
161 &dwLocalGroupRead,
162 &dwLocalGroupTotal);
163 if (Status != NERR_Success)
164 goto done;
165
166 Status = NetUserGetGroups(NULL,
167 lpUserName,
168 0,
169 (LPBYTE*)&pGroupInfo,
170 MAX_PREFERRED_LENGTH,
171 &dwGroupRead,
172 &dwGroupTotal);
173 if (Status != NERR_Success)
174 goto done;
175
176 PrintToConsole(L"User name %s\n", pUserInfo->usri4_name);
177 PrintToConsole(L"Full name %s\n", pUserInfo->usri4_full_name);
178 PrintToConsole(L"Comment %s\n", pUserInfo->usri4_comment);
179 PrintToConsole(L"User comment %s\n", pUserInfo->usri4_usr_comment);
180 PrintToConsole(L"Country code %03ld ()\n", pUserInfo->usri4_country_code);
181 PrintToConsole(L"Account active %s\n", (pUserInfo->usri4_flags & UF_ACCOUNTDISABLE)? L"No" : ((pUserInfo->usri4_flags & UF_LOCKOUT) ? L"Locked" : L"Yes"));
182 PrintToConsole(L"Account expires ");
183 if (pUserInfo->usri4_acct_expires == TIMEQ_FOREVER)
184 PrintToConsole(L"Never\n");
185 else
186 PrintDateTime(pUserInfo->usri4_acct_expires);
187
188 PrintToConsole(L"\n");
189
190 PrintToConsole(L"Password last set ");
191 dwLastSet = GetTimeInSeconds() - pUserInfo->usri4_password_age;
192 PrintDateTime(dwLastSet);
193
194 PrintToConsole(L"Password expires ");
195 if ((pUserInfo->usri4_flags & UF_DONT_EXPIRE_PASSWD) || pUserModals->usrmod0_max_passwd_age == TIMEQ_FOREVER)
196 PrintToConsole(L"Never\n");
197 else
198 PrintDateTime(dwLastSet + pUserModals->usrmod0_max_passwd_age);
199
200 PrintToConsole(L"Password changeable ");
201 PrintDateTime(dwLastSet + pUserModals->usrmod0_min_passwd_age);
202
203 PrintToConsole(L"Password required %s\n", (pUserInfo->usri4_flags & UF_PASSWD_NOTREQD) ? L"No" : L"Yes");
204 PrintToConsole(L"User may change password %s\n", (pUserInfo->usri4_flags & UF_PASSWD_CANT_CHANGE) ? L"No" : L"Yes");
205
206 PrintToConsole(L"\n");
207 PrintToConsole(L"Workstations allowed %s\n", (pUserInfo->usri4_workstations == NULL || wcslen(pUserInfo->usri4_workstations) == 0) ? L"All" : pUserInfo->usri4_workstations);
208 PrintToConsole(L"Logon script %s\n", pUserInfo->usri4_script_path);
209 PrintToConsole(L"User profile %s\n", pUserInfo->usri4_profile);
210 PrintToConsole(L"Home directory %s\n", pUserInfo->usri4_home_dir);
211 PrintToConsole(L"Last logon ");
212 if (pUserInfo->usri4_last_logon == 0)
213 PrintToConsole(L"Never\n");
214 else
215 PrintDateTime(pUserInfo->usri4_last_logon);
216 PrintToConsole(L"\n");
217 PrintToConsole(L"Logon hours allowed ");
218 if (pUserInfo->usri4_logon_hours == NULL)
219 PrintToConsole(L"All\n");
220 PrintToConsole(L"\n");
221
222 PrintToConsole(L"\n");
223 PrintToConsole(L"Local group memberships ");
224 if (dwLocalGroupTotal != 0 && pLocalGroupInfo != NULL)
225 {
226 for (i = 0; i < dwLocalGroupTotal; i++)
227 {
228 if (i != 0)
229 PrintToConsole(L" ");
230 PrintToConsole(L"*%s\n", pLocalGroupInfo[i].lgrui0_name);
231 }
232 }
233 else
234 {
235 PrintToConsole(L"\n");
236 }
237
238 PrintToConsole(L"Global group memberships ");
239 if (dwGroupTotal != 0 && pGroupInfo != NULL)
240 {
241 for (i = 0; i < dwGroupTotal; i++)
242 {
243 if (i != 0)
244 PrintToConsole(L" ");
245 PrintToConsole(L"*%s\n", pGroupInfo[i].grui0_name);
246 }
247 }
248 else
249 {
250 PrintToConsole(L"\n");
251 }
252
253 done:
254 if (pGroupInfo != NULL)
255 NetApiBufferFree(pGroupInfo);
256
257 if (pLocalGroupInfo != NULL)
258 NetApiBufferFree(pLocalGroupInfo);
259
260 if (pUserModals != NULL)
261 NetApiBufferFree(pUserModals);
262
263 if (pUserInfo != NULL)
264 NetApiBufferFree(pUserInfo);
265
266 return NERR_Success;
267 }
268
269
270 INT
271 cmdUser(
272 INT argc,
273 WCHAR **argv)
274 {
275 INT i, j;
276 INT result = 0;
277 BOOL bAdd = FALSE;
278 BOOL bDelete = FALSE;
279 #if 0
280 BOOL bDomain = FALSE;
281 #endif
282 LPWSTR lpUserName = NULL;
283 LPWSTR lpPassword = NULL;
284 PUSER_INFO_4 pUserInfo = NULL;
285 USER_INFO_4 UserInfo;
286 LPWSTR p;
287 LPWSTR endptr;
288 DWORD value;
289 NET_API_STATUS Status;
290
291 if (argc == 2)
292 {
293 Status = EnumerateUsers();
294 printf("Status: %lu\n", Status);
295 return 0;
296 }
297 else if (argc == 3)
298 {
299 Status = DisplayUser(argv[2]);
300 printf("Status: %lu\n", Status);
301 return 0;
302 }
303
304 i = 2;
305 if (argv[i][0] != L'/')
306 {
307 lpUserName = argv[i];
308 printf("User: %S\n", lpUserName);
309 i++;
310 }
311
312 if (argv[i][0] != L'/')
313 {
314 lpPassword = argv[i];
315 printf("Password: %S\n", lpPassword);
316 i++;
317 }
318
319 for (j = i; j < argc; j++)
320 {
321 if (_wcsicmp(argv[j], L"/help") == 0)
322 {
323 PrintResourceString(IDS_USER_HELP);
324 return 0;
325 }
326 else if (_wcsicmp(argv[j], L"/add") == 0)
327 {
328 bAdd = TRUE;
329 }
330 else if (_wcsicmp(argv[j], L"/delete") == 0)
331 {
332 bDelete = TRUE;
333 }
334 else if (_wcsicmp(argv[j], L"/domain") == 0)
335 {
336 printf("The /DOMAIN option is not supported yet!\n");
337 #if 0
338 bDomain = TRUE;
339 #endif
340 }
341 }
342
343 if (bAdd && bDelete)
344 {
345 result = 1;
346 goto done;
347 }
348
349 if (!bAdd && !bDelete)
350 {
351 /* Modify the user */
352 Status = NetUserGetInfo(NULL,
353 lpUserName,
354 4,
355 (LPBYTE*)&pUserInfo);
356 if (Status != NERR_Success)
357 {
358 printf("Status: %lu\n", Status);
359 result = 1;
360 goto done;
361 }
362 }
363 else if (bAdd && !bDelete)
364 {
365 /* Add the user */
366 ZeroMemory(&UserInfo, sizeof(USER_INFO_4));
367
368 UserInfo.usri4_name = lpUserName;
369 UserInfo.usri4_password = lpPassword;
370 UserInfo.usri4_flags = UF_SCRIPT | UF_NORMAL_ACCOUNT;
371
372 pUserInfo = &UserInfo;
373 }
374
375 for (j = i; j < argc; j++)
376 {
377 if (_wcsnicmp(argv[j], L"/active:", 8) == 0)
378 {
379 p = &argv[i][8];
380 if (_wcsicmp(p, L"yes") == 0)
381 {
382 pUserInfo->usri4_flags &= ~UF_ACCOUNTDISABLE;
383 }
384 else if (_wcsicmp(p, L"no") == 0)
385 {
386 pUserInfo->usri4_flags |= UF_ACCOUNTDISABLE;
387 }
388 else
389 {
390 PrintToConsole(L"You entered an invalid value for the /ACTIVE option.\n");
391 result = 1;
392 goto done;
393 }
394 }
395 else if (_wcsnicmp(argv[j], L"/comment:", 9) == 0)
396 {
397 pUserInfo->usri4_comment = &argv[j][9];
398 }
399 else if (_wcsnicmp(argv[j], L"/countrycode:", 13) == 0)
400 {
401 p = &argv[i][13];
402 value = wcstoul(p, &endptr, 10);
403 if (*endptr != 0)
404 {
405 PrintToConsole(L"You entered an invalid value for the /COUNTRYCODE option.\n");
406 result = 1;
407 goto done;
408 }
409
410 /* FIXME: verify the country code */
411
412 pUserInfo->usri4_country_code = value;
413 }
414 else if (_wcsnicmp(argv[j], L"/expires:", 9) == 0)
415 {
416 }
417 else if (_wcsnicmp(argv[j], L"/fullname:", 10) == 0)
418 {
419 pUserInfo->usri4_full_name = &argv[j][10];
420 }
421 else if (_wcsnicmp(argv[j], L"/homedir:", 9) == 0)
422 {
423 pUserInfo->usri4_home_dir = &argv[j][9];
424 }
425 else if (_wcsnicmp(argv[j], L"/passwordchg:", 13) == 0)
426 {
427 p = &argv[i][13];
428 if (_wcsicmp(p, L"yes") == 0)
429 {
430 pUserInfo->usri4_flags &= ~UF_PASSWD_CANT_CHANGE;
431 }
432 else if (_wcsicmp(p, L"no") == 0)
433 {
434 pUserInfo->usri4_flags |= UF_PASSWD_CANT_CHANGE;
435 }
436 else
437 {
438 PrintToConsole(L"You entered an invalid value for the /PASSWORDCHG option.\n");
439 result = 1;
440 goto done;
441 }
442 }
443 else if (_wcsnicmp(argv[j], L"/passwordreq:", 13) == 0)
444 {
445 p = &argv[i][13];
446 if (_wcsicmp(p, L"yes") == 0)
447 {
448 pUserInfo->usri4_flags &= ~UF_PASSWD_NOTREQD;
449 }
450 else if (_wcsicmp(p, L"no") == 0)
451 {
452 pUserInfo->usri4_flags |= UF_PASSWD_NOTREQD;
453 }
454 else
455 {
456 PrintToConsole(L"You entered an invalid value for the /PASSWORDREQ option.\n");
457 result = 1;
458 goto done;
459 }
460 }
461 else if (_wcsnicmp(argv[j], L"/profilepath:", 13) == 0)
462 {
463 pUserInfo->usri4_profile = &argv[j][13];
464 }
465 else if (_wcsnicmp(argv[j], L"/scriptpath:", 12) == 0)
466 {
467 pUserInfo->usri4_script_path = &argv[j][12];
468 }
469 else if (_wcsnicmp(argv[j], L"/times:", 7) == 0)
470 {
471 }
472 else if (_wcsnicmp(argv[j], L"/usercomment:", 13) == 0)
473 {
474 pUserInfo->usri4_usr_comment = &argv[j][13];
475 }
476 else if (_wcsnicmp(argv[j], L"/workstations:", 14) == 0)
477 {
478 }
479 }
480
481 if (!bAdd && !bDelete)
482 {
483 /* Modify the user */
484 Status = NetUserSetInfo(NULL,
485 lpUserName,
486 4,
487 (LPBYTE)pUserInfo,
488 NULL);
489 printf("Status: %lu\n", Status);
490 }
491 else if (bAdd && !bDelete)
492 {
493 /* Add the user */
494 Status = NetUserAdd(NULL,
495 4,
496 (LPBYTE)pUserInfo,
497 NULL);
498 printf("Status: %lu\n", Status);
499 }
500 else if (!bAdd && bDelete)
501 {
502 /* Delete the user */
503 Status = NetUserDel(NULL,
504 lpUserName);
505 printf("Status: %lu\n", Status);
506 }
507
508 done:
509 if (!bAdd && !bDelete && pUserInfo != NULL)
510 NetApiBufferFree(pUserInfo);
511
512 if (result != 0)
513 PrintResourceString(IDS_USER_SYNTAX);
514
515 return result;
516 }
517
518 /* EOF */