[NET]
[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 PrintPaddedResourceString(IDS_USER_NAME);
177 PrintToConsole(L"%s\n", pUserInfo->usri4_name);
178
179 PrintPaddedResourceString(IDS_USER_FULL_NAME);
180 PrintToConsole(L"%s\n", pUserInfo->usri4_full_name);
181
182 PrintPaddedResourceString(IDS_USER_COMMENT);
183 PrintToConsole(L"%s\n", pUserInfo->usri4_comment);
184
185 PrintPaddedResourceString(IDS_USER_USER_COMMENT);
186 PrintToConsole(L"%s\n", pUserInfo->usri4_usr_comment);
187
188 PrintPaddedResourceString(IDS_USER_COUNTRY_CODE);
189 PrintToConsole(L"%03ld ()\n", pUserInfo->usri4_country_code);
190
191 PrintPaddedResourceString(IDS_USER_ACCOUNT_ACTIVE);
192 PrintToConsole(L"%s\n", (pUserInfo->usri4_flags & UF_ACCOUNTDISABLE)? L"No" : ((pUserInfo->usri4_flags & UF_LOCKOUT) ? L"Locked" : L"Yes"));
193
194 PrintPaddedResourceString(IDS_USER_ACCOUNT_EXPIRES);
195 if (pUserInfo->usri4_acct_expires == TIMEQ_FOREVER)
196 PrintToConsole(L"Never\n");
197 else
198 PrintDateTime(pUserInfo->usri4_acct_expires);
199
200 PrintToConsole(L"\n");
201
202 PrintPaddedResourceString(IDS_USER_PW_LAST_SET);
203 dwLastSet = GetTimeInSeconds() - pUserInfo->usri4_password_age;
204 PrintDateTime(dwLastSet);
205
206 PrintPaddedResourceString(IDS_USER_PW_EXPIRES);
207 if ((pUserInfo->usri4_flags & UF_DONT_EXPIRE_PASSWD) || pUserModals->usrmod0_max_passwd_age == TIMEQ_FOREVER)
208 PrintToConsole(L"Never\n");
209 else
210 PrintDateTime(dwLastSet + pUserModals->usrmod0_max_passwd_age);
211
212 PrintPaddedResourceString(IDS_USER_PW_CHANGEABLE);
213 PrintDateTime(dwLastSet + pUserModals->usrmod0_min_passwd_age);
214
215 PrintPaddedResourceString(IDS_USER_PW_REQUIRED);
216 PrintToConsole(L"%s\n", (pUserInfo->usri4_flags & UF_PASSWD_NOTREQD) ? L"No" : L"Yes");
217
218 PrintPaddedResourceString(IDS_USER_CHANGE_PW);
219 PrintToConsole(L"%s\n", (pUserInfo->usri4_flags & UF_PASSWD_CANT_CHANGE) ? L"No" : L"Yes");
220
221 PrintToConsole(L"\n");
222
223 PrintPaddedResourceString(IDS_USER_WORKSTATIONS);
224 PrintToConsole(L"%s\n", (pUserInfo->usri4_workstations == NULL || wcslen(pUserInfo->usri4_workstations) == 0) ? L"All" : pUserInfo->usri4_workstations);
225
226 PrintPaddedResourceString(IDS_USER_LOGON_SCRIPT);
227 PrintToConsole(L"%s\n", pUserInfo->usri4_script_path);
228
229 PrintPaddedResourceString(IDS_USER_PROFILE);
230 PrintToConsole(L"%s\n", pUserInfo->usri4_profile);
231
232 PrintPaddedResourceString(IDS_USER_HOME_DIR);
233 PrintToConsole(L"%s\n", pUserInfo->usri4_home_dir);
234
235 PrintPaddedResourceString(IDS_USER_LAST_LOGON);
236 if (pUserInfo->usri4_last_logon == 0)
237 PrintToConsole(L"Never\n");
238 else
239 PrintDateTime(pUserInfo->usri4_last_logon);
240
241 PrintToConsole(L"\n");
242
243 PrintPaddedResourceString(IDS_USER_LOGON_HOURS);
244 if (pUserInfo->usri4_logon_hours == NULL)
245 PrintToConsole(L"All\n");
246
247 PrintToConsole(L"\n");
248
249 PrintToConsole(L"\n");
250 PrintPaddedResourceString(IDS_USER_LOCAL_GROUPS);
251 if (dwLocalGroupTotal != 0 && pLocalGroupInfo != NULL)
252 {
253 for (i = 0; i < dwLocalGroupTotal; i++)
254 {
255 if (i != 0)
256 PrintToConsole(L" ");
257 PrintToConsole(L"*%s\n", pLocalGroupInfo[i].lgrui0_name);
258 }
259 }
260 else
261 {
262 PrintToConsole(L"\n");
263 }
264
265 PrintPaddedResourceString(IDS_USER_GLOBAL_GROUPS);
266 if (dwGroupTotal != 0 && pGroupInfo != NULL)
267 {
268 for (i = 0; i < dwGroupTotal; i++)
269 {
270 if (i != 0)
271 PrintToConsole(L" ");
272 PrintToConsole(L"*%s\n", pGroupInfo[i].grui0_name);
273 }
274 }
275 else
276 {
277 PrintToConsole(L"\n");
278 }
279
280 done:
281 if (pGroupInfo != NULL)
282 NetApiBufferFree(pGroupInfo);
283
284 if (pLocalGroupInfo != NULL)
285 NetApiBufferFree(pLocalGroupInfo);
286
287 if (pUserModals != NULL)
288 NetApiBufferFree(pUserModals);
289
290 if (pUserInfo != NULL)
291 NetApiBufferFree(pUserInfo);
292
293 return NERR_Success;
294 }
295
296
297 static
298 VOID
299 ReadPassword(
300 LPWSTR *lpPassword,
301 LPBOOL lpAllocated)
302 {
303 WCHAR szPassword1[PWLEN + 1];
304 WCHAR szPassword2[PWLEN + 1];
305 LPWSTR ptr;
306
307 *lpAllocated = FALSE;
308
309 while (TRUE)
310 {
311 PrintResourceString(IDS_USER_ENTER_PASSWORD1);
312 ReadFromConsole(szPassword1, PWLEN + 1, FALSE);
313 printf("\n");
314
315 PrintResourceString(IDS_USER_ENTER_PASSWORD2);
316 ReadFromConsole(szPassword2, PWLEN + 1, FALSE);
317 printf("\n");
318
319 if (wcslen(szPassword1) == wcslen(szPassword2) &&
320 wcscmp(szPassword1, szPassword2) == 0)
321 {
322 ptr = HeapAlloc(GetProcessHeap(),
323 0,
324 (wcslen(szPassword1) + 1) * sizeof(WCHAR));
325 if (ptr != NULL)
326 {
327 wcscpy(ptr, szPassword1);
328 *lpPassword = ptr;
329 *lpAllocated = TRUE;
330 return;
331 }
332 }
333 else
334 {
335 PrintResourceString(IDS_USER_NO_PASSWORD_MATCH);
336 *lpPassword = NULL;
337 }
338 }
339 }
340
341
342 INT
343 cmdUser(
344 INT argc,
345 WCHAR **argv)
346 {
347 INT i, j;
348 INT result = 0;
349 BOOL bAdd = FALSE;
350 BOOL bDelete = FALSE;
351 #if 0
352 BOOL bDomain = FALSE;
353 #endif
354 LPWSTR lpUserName = NULL;
355 LPWSTR lpPassword = NULL;
356 PUSER_INFO_4 pUserInfo = NULL;
357 USER_INFO_4 UserInfo;
358 LPWSTR p;
359 LPWSTR endptr;
360 DWORD value;
361 BOOL bPasswordAllocated = FALSE;
362 NET_API_STATUS Status;
363
364 if (argc == 2)
365 {
366 Status = EnumerateUsers();
367 printf("Status: %lu\n", Status);
368 return 0;
369 }
370 else if (argc == 3)
371 {
372 Status = DisplayUser(argv[2]);
373 printf("Status: %lu\n", Status);
374 return 0;
375 }
376
377 i = 2;
378 if (argv[i][0] != L'/')
379 {
380 lpUserName = argv[i];
381 // printf("User: %S\n", lpUserName);
382 i++;
383 }
384
385 if (argv[i][0] != L'/')
386 {
387 lpPassword = argv[i];
388 // printf("Password: %S\n", lpPassword);
389 i++;
390 }
391
392 for (j = i; j < argc; j++)
393 {
394 if (_wcsicmp(argv[j], L"/help") == 0)
395 {
396 PrintResourceString(IDS_USER_HELP);
397 return 0;
398 }
399 else if (_wcsicmp(argv[j], L"/add") == 0)
400 {
401 bAdd = TRUE;
402 }
403 else if (_wcsicmp(argv[j], L"/delete") == 0)
404 {
405 bDelete = TRUE;
406 }
407 else if (_wcsicmp(argv[j], L"/domain") == 0)
408 {
409 PrintResourceString(IDS_ERROR_OPTION_NOT_SUPPORTED, L"/DOMAIN");
410 #if 0
411 bDomain = TRUE;
412 #endif
413 }
414 }
415
416 if (bAdd && bDelete)
417 {
418 result = 1;
419 goto done;
420 }
421
422 /* Interactive password input */
423 if (lpPassword != NULL && wcscmp(lpPassword, L"*") == 0)
424 {
425 ReadPassword(&lpPassword,
426 &bPasswordAllocated);
427 }
428
429 if (!bAdd && !bDelete)
430 {
431 /* Modify the user */
432 Status = NetUserGetInfo(NULL,
433 lpUserName,
434 4,
435 (LPBYTE*)&pUserInfo);
436 if (Status != NERR_Success)
437 {
438 printf("Status: %lu\n", Status);
439 result = 1;
440 goto done;
441 }
442 }
443 else if (bAdd && !bDelete)
444 {
445 /* Add the user */
446 ZeroMemory(&UserInfo, sizeof(USER_INFO_4));
447
448 UserInfo.usri4_name = lpUserName;
449 UserInfo.usri4_password = lpPassword;
450 UserInfo.usri4_flags = UF_SCRIPT | UF_NORMAL_ACCOUNT;
451
452 pUserInfo = &UserInfo;
453 }
454
455 for (j = i; j < argc; j++)
456 {
457 if (_wcsnicmp(argv[j], L"/active:", 8) == 0)
458 {
459 p = &argv[i][8];
460 if (_wcsicmp(p, L"yes") == 0)
461 {
462 pUserInfo->usri4_flags &= ~UF_ACCOUNTDISABLE;
463 }
464 else if (_wcsicmp(p, L"no") == 0)
465 {
466 pUserInfo->usri4_flags |= UF_ACCOUNTDISABLE;
467 }
468 else
469 {
470 PrintResourceString(IDS_ERROR_INVALID_OPTION_VALUE, L"/ACTIVE");
471 result = 1;
472 goto done;
473 }
474 }
475 else if (_wcsnicmp(argv[j], L"/comment:", 9) == 0)
476 {
477 pUserInfo->usri4_comment = &argv[j][9];
478 }
479 else if (_wcsnicmp(argv[j], L"/countrycode:", 13) == 0)
480 {
481 p = &argv[i][13];
482 value = wcstoul(p, &endptr, 10);
483 if (*endptr != 0)
484 {
485 PrintResourceString(IDS_ERROR_INVALID_OPTION_VALUE, L"/COUNTRYCODE");
486 result = 1;
487 goto done;
488 }
489
490 /* FIXME: verify the country code */
491
492 pUserInfo->usri4_country_code = value;
493 }
494 else if (_wcsnicmp(argv[j], L"/expires:", 9) == 0)
495 {
496 p = &argv[i][9];
497 if (_wcsicmp(p, L"never") == 0)
498 {
499 pUserInfo->usri4_acct_expires = TIMEQ_FOREVER;
500 }
501 else
502 {
503 /* FIXME: Parse the date */
504 PrintResourceString(IDS_ERROR_OPTION_NOT_SUPPORTED, L"/EXPIRES");
505 }
506 }
507 else if (_wcsnicmp(argv[j], L"/fullname:", 10) == 0)
508 {
509 pUserInfo->usri4_full_name = &argv[j][10];
510 }
511 else if (_wcsnicmp(argv[j], L"/homedir:", 9) == 0)
512 {
513 pUserInfo->usri4_home_dir = &argv[j][9];
514 }
515 else if (_wcsnicmp(argv[j], L"/passwordchg:", 13) == 0)
516 {
517 p = &argv[i][13];
518 if (_wcsicmp(p, L"yes") == 0)
519 {
520 pUserInfo->usri4_flags &= ~UF_PASSWD_CANT_CHANGE;
521 }
522 else if (_wcsicmp(p, L"no") == 0)
523 {
524 pUserInfo->usri4_flags |= UF_PASSWD_CANT_CHANGE;
525 }
526 else
527 {
528 PrintResourceString(IDS_ERROR_INVALID_OPTION_VALUE, L"/PASSWORDCHG");
529 result = 1;
530 goto done;
531 }
532 }
533 else if (_wcsnicmp(argv[j], L"/passwordreq:", 13) == 0)
534 {
535 p = &argv[i][13];
536 if (_wcsicmp(p, L"yes") == 0)
537 {
538 pUserInfo->usri4_flags &= ~UF_PASSWD_NOTREQD;
539 }
540 else if (_wcsicmp(p, L"no") == 0)
541 {
542 pUserInfo->usri4_flags |= UF_PASSWD_NOTREQD;
543 }
544 else
545 {
546 PrintResourceString(IDS_ERROR_INVALID_OPTION_VALUE, L"/PASSWORDREQ");
547 result = 1;
548 goto done;
549 }
550 }
551 else if (_wcsnicmp(argv[j], L"/profilepath:", 13) == 0)
552 {
553 pUserInfo->usri4_profile = &argv[j][13];
554 }
555 else if (_wcsnicmp(argv[j], L"/scriptpath:", 12) == 0)
556 {
557 pUserInfo->usri4_script_path = &argv[j][12];
558 }
559 else if (_wcsnicmp(argv[j], L"/times:", 7) == 0)
560 {
561 /* FIXME */
562 PrintResourceString(IDS_ERROR_OPTION_NOT_SUPPORTED, L"/TIMES");
563 }
564 else if (_wcsnicmp(argv[j], L"/usercomment:", 13) == 0)
565 {
566 pUserInfo->usri4_usr_comment = &argv[j][13];
567 }
568 else if (_wcsnicmp(argv[j], L"/workstations:", 14) == 0)
569 {
570 /* FIXME */
571 PrintResourceString(IDS_ERROR_OPTION_NOT_SUPPORTED, L"/WORKSTATIONS");
572 }
573 }
574
575 if (!bAdd && !bDelete)
576 {
577 /* Modify the user */
578 Status = NetUserSetInfo(NULL,
579 lpUserName,
580 4,
581 (LPBYTE)pUserInfo,
582 NULL);
583 printf("Status: %lu\n", Status);
584 }
585 else if (bAdd && !bDelete)
586 {
587 /* Add the user */
588 Status = NetUserAdd(NULL,
589 4,
590 (LPBYTE)pUserInfo,
591 NULL);
592 printf("Status: %lu\n", Status);
593 }
594 else if (!bAdd && bDelete)
595 {
596 /* Delete the user */
597 Status = NetUserDel(NULL,
598 lpUserName);
599 printf("Status: %lu\n", Status);
600 }
601
602 done:
603 if (bPasswordAllocated == TRUE && lpPassword != NULL)
604 HeapFree(GetProcessHeap(), 0, lpPassword);
605
606 if (!bAdd && !bDelete && pUserInfo != NULL)
607 NetApiBufferFree(pUserInfo);
608
609 if (result != 0)
610 PrintResourceString(IDS_USER_SYNTAX);
611
612 return result;
613 }
614
615 /* EOF */