81506ea6cec19918a3c8c6e02aa0d90009376c55
[reactos.git] / base / applications / network / net / cmdUser.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS net command
4 * FILE: base/applications/network/net/cmdUser.c
5 * PURPOSE:
6 *
7 * PROGRAMMERS: Eric Kohl
8 * Curtis Wilson
9 */
10
11 #include "net.h"
12
13 #define SECONDS_PER_DAY (60 * 60 * 24)
14 #define SECONDS_PER_HOUR (60 * 60)
15
16 typedef struct _COUNTY_TABLE
17 {
18 DWORD dwCountryCode;
19 DWORD dwMessageId;
20 } COUNTRY_TABLE, *PCOUNTRY_TABLE;
21
22
23 static WCHAR szPasswordChars[] = L"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@#$%_-+:";
24 static COUNTRY_TABLE CountryTable[] =
25 { { 0, 5080}, // System Default
26 { 1, 5081}, // United States
27 { 2, 5082}, // Canada (French)
28 { 3, 5083}, // Latin America
29 { 31, 5084}, // Netherlands
30 { 32, 5085}, // Belgium
31 { 33, 5086}, // France
32 { 34, 5090}, // Spain
33 { 39, 5087}, // Italy
34 { 41, 5088}, // Switzerland
35 { 44, 5089}, // United Kingdom
36 { 45, 5091}, // Denmark
37 { 46, 5092}, // Sweden
38 { 47, 5093}, // Norway
39 { 49, 5094}, // Germany
40 { 61, 5095}, // Australia
41 { 81, 5096}, // Japan
42 { 82, 5097}, // Korea
43 { 86, 5098}, // China (PRC)
44 { 88, 5099}, // Taiwan
45 { 99, 5100}, // Asia
46 {351, 5101}, // Portugal
47 {358, 5102}, // Finland
48 {785, 5103}, // Arabic
49 {972, 5104} }; // Hebrew
50
51
52 static
53 int
54 CompareInfo(const void *a, const void *b)
55 {
56 return _wcsicmp(((PUSER_INFO_0)a)->usri0_name,
57 ((PUSER_INFO_0)b)->usri0_name);
58 }
59
60
61 static
62 NET_API_STATUS
63 EnumerateUsers(VOID)
64 {
65 PUSER_INFO_0 pBuffer = NULL;
66 PSERVER_INFO_100 pServer = NULL;
67 DWORD dwRead = 0, dwTotal = 0;
68 DWORD i;
69 DWORD ResumeHandle = 0;
70 NET_API_STATUS Status;
71
72 Status = NetServerGetInfo(NULL,
73 100,
74 (LPBYTE*)&pServer);
75 if (Status != NERR_Success)
76 return Status;
77
78 ConPuts(StdOut, L"\n");
79 PrintMessageStringV(4410, pServer->sv100_name);
80 ConPuts(StdOut, L"\n");
81 PrintPadding(L'-', 79);
82 ConPuts(StdOut, L"\n");
83
84 NetApiBufferFree(pServer);
85
86 do
87 {
88 Status = NetUserEnum(NULL,
89 0,
90 0,
91 (LPBYTE*)&pBuffer,
92 MAX_PREFERRED_LENGTH,
93 &dwRead,
94 &dwTotal,
95 &ResumeHandle);
96 if ((Status != NERR_Success) && (Status != ERROR_MORE_DATA))
97 return Status;
98
99 qsort(pBuffer,
100 dwRead,
101 sizeof(PUSER_INFO_0),
102 CompareInfo);
103
104 for (i = 0; i < dwRead; i++)
105 {
106 if (pBuffer[i].usri0_name)
107 ConPrintf(StdOut, L"%s\n", pBuffer[i].usri0_name);
108 }
109
110 NetApiBufferFree(pBuffer);
111 pBuffer = NULL;
112 }
113 while (Status == ERROR_MORE_DATA);
114
115 return NERR_Success;
116 }
117
118
119 static
120 VOID
121 PrintDateTime(DWORD dwSeconds)
122 {
123 LARGE_INTEGER Time;
124 FILETIME FileTime;
125 SYSTEMTIME SystemTime;
126 WCHAR DateBuffer[80];
127 WCHAR TimeBuffer[80];
128
129 RtlSecondsSince1970ToTime(dwSeconds, &Time);
130 FileTime.dwLowDateTime = Time.u.LowPart;
131 FileTime.dwHighDateTime = Time.u.HighPart;
132 FileTimeToLocalFileTime(&FileTime, &FileTime);
133 FileTimeToSystemTime(&FileTime, &SystemTime);
134
135 GetDateFormatW(LOCALE_USER_DEFAULT,
136 DATE_SHORTDATE,
137 &SystemTime,
138 NULL,
139 DateBuffer,
140 ARRAYSIZE(DateBuffer));
141
142 GetTimeFormatW(LOCALE_USER_DEFAULT,
143 TIME_NOSECONDS,
144 &SystemTime,
145 NULL,
146 TimeBuffer,
147 ARRAYSIZE(TimeBuffer));
148
149 ConPrintf(StdOut, L"%s %s", DateBuffer, TimeBuffer);
150 }
151
152
153 static
154 VOID
155 PrintLocalTime(DWORD dwSeconds)
156 {
157 LARGE_INTEGER Time;
158 FILETIME FileTime;
159 SYSTEMTIME SystemTime;
160 WCHAR TimeBuffer[80];
161
162 RtlSecondsSince1970ToTime(dwSeconds, &Time);
163 FileTime.dwLowDateTime = Time.u.LowPart;
164 FileTime.dwHighDateTime = Time.u.HighPart;
165 FileTimeToSystemTime(&FileTime, &SystemTime);
166
167 GetTimeFormatW(LOCALE_USER_DEFAULT,
168 TIME_NOSECONDS,
169 &SystemTime,
170 NULL,
171 TimeBuffer,
172 ARRAYSIZE(TimeBuffer));
173
174 ConPrintf(StdOut, L"%s", TimeBuffer);
175 }
176
177
178 static
179 DWORD
180 GetTimeInSeconds(VOID)
181 {
182 LARGE_INTEGER Time;
183 FILETIME FileTime;
184 DWORD dwSeconds;
185
186 GetSystemTimeAsFileTime(&FileTime);
187 Time.u.LowPart = FileTime.dwLowDateTime;
188 Time.u.HighPart = FileTime.dwHighDateTime;
189 RtlTimeToSecondsSince1970(&Time, &dwSeconds);
190
191 return dwSeconds;
192 }
193
194
195 static
196 BOOL
197 GetCountryFromCountryCode(
198 _In_ DWORD dwCountryCode,
199 _In_ DWORD dwCountryLength,
200 _Out_ PWSTR szCountryBuffer)
201 {
202 DWORD i;
203
204 for (i = 0; i < ARRAYSIZE(CountryTable); i++)
205 {
206 if (CountryTable[i].dwCountryCode == dwCountryCode)
207 {
208 if (szCountryBuffer != NULL && dwCountryLength > 0)
209 {
210 FormatMessageW(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS,
211 hModuleNetMsg,
212 CountryTable[i].dwMessageId,
213 LANG_USER_DEFAULT,
214 szCountryBuffer,
215 dwCountryLength,
216 NULL);
217 }
218
219 return TRUE;
220 }
221 }
222
223 return FALSE;
224 }
225
226
227 static
228 BOOL
229 BitValue(
230 PBYTE pLogonHours,
231 DWORD dwBitNumber)
232 {
233 DWORD dwIndex = dwBitNumber / 8;
234 BYTE Mask = 1 << (dwBitNumber & 7);
235
236 return ((pLogonHours[dwIndex] & Mask) != 0);
237 }
238
239
240 static
241 VOID
242 PrintLogonHours(
243 DWORD dwUnitsPerWeek,
244 PBYTE pLogonHours,
245 INT nPaddedLength)
246 {
247 DWORD dwUnitsPerDay, dwBitNumber, dwSecondsPerUnit;
248 DWORD dwStartTime, dwEndTime, dwStartDay, dwEndDay;
249 BOOL bBitValue, bFirst = TRUE;
250
251 if ((dwUnitsPerWeek == 0) ||
252 ((dwUnitsPerWeek %7) != 0))
253 return;
254
255 dwUnitsPerDay = dwUnitsPerWeek / 7;
256
257 if (((dwUnitsPerDay % 24) != 0) ||
258 ((dwUnitsPerDay / 24) > 6))
259 return;
260
261 dwSecondsPerUnit = (SECONDS_PER_DAY) / dwUnitsPerDay;
262
263 for (dwBitNumber = 0; dwBitNumber < dwUnitsPerWeek; dwBitNumber++)
264 {
265 bBitValue = BitValue(pLogonHours, dwBitNumber);
266 if (bBitValue)
267 {
268 dwStartTime = dwSecondsPerUnit * dwBitNumber;
269
270 while (bBitValue != 0 && dwBitNumber < dwUnitsPerWeek)
271 {
272 dwBitNumber++;
273 if (dwBitNumber < dwUnitsPerWeek)
274 bBitValue = BitValue(pLogonHours, dwBitNumber);
275 }
276
277 dwEndTime = dwSecondsPerUnit * dwBitNumber;
278
279 if (!bFirst)
280 PrintPadding(L' ', nPaddedLength);
281
282 if (dwStartTime == 0 && dwEndTime == (SECONDS_PER_DAY * 7))
283 {
284 PrintMessageString(4302);
285 ConPuts(StdOut, L"\n");
286 }
287 else
288 {
289 dwStartDay = dwStartTime / SECONDS_PER_DAY;
290 dwEndDay = (dwEndTime / SECONDS_PER_DAY) % 7;
291
292 PrintMessageString(4307 + dwStartDay);
293 ConPuts(StdOut, L" ");
294 PrintLocalTime((dwStartTime % SECONDS_PER_DAY) + SECONDS_PER_HOUR);
295
296 ConPrintf(StdOut, L" - ");
297 if (dwStartDay != dwEndDay)
298 {
299 PrintMessageString(4307 + dwEndDay);
300 ConPuts(StdOut, L" ");
301 }
302
303 PrintLocalTime((dwEndTime % SECONDS_PER_DAY) + SECONDS_PER_HOUR);
304 ConPuts(StdOut, L"\n");
305 }
306
307 bFirst = FALSE;
308 }
309 }
310
311 if (bFirst)
312 {
313 /* No logon hours */
314 PrintMessageString(4434);
315 ConPuts(StdOut, L"\n");
316 }
317 }
318
319
320 static
321 NET_API_STATUS
322 DisplayUser(LPWSTR lpUserName)
323 {
324 PUSER_MODALS_INFO_0 pUserModals = NULL;
325 PUSER_INFO_4 pUserInfo = NULL;
326 PLOCALGROUP_USERS_INFO_0 pLocalGroupInfo = NULL;
327 PGROUP_USERS_INFO_0 pGroupInfo = NULL;
328 DWORD dwLocalGroupRead, dwLocalGroupTotal;
329 DWORD dwGroupRead, dwGroupTotal;
330 DWORD dwLastSet;
331 DWORD i;
332 WCHAR szCountry[40];
333 INT nPaddedLength = 36;
334 NET_API_STATUS Status;
335
336 /* Modify the user */
337 Status = NetUserGetInfo(NULL,
338 lpUserName,
339 4,
340 (LPBYTE*)&pUserInfo);
341 if (Status != NERR_Success)
342 return Status;
343
344 Status = NetUserModalsGet(NULL,
345 0,
346 (LPBYTE*)&pUserModals);
347 if (Status != NERR_Success)
348 goto done;
349
350 Status = NetUserGetLocalGroups(NULL,
351 lpUserName,
352 0,
353 0,
354 (LPBYTE*)&pLocalGroupInfo,
355 MAX_PREFERRED_LENGTH,
356 &dwLocalGroupRead,
357 &dwLocalGroupTotal);
358 if (Status != NERR_Success)
359 goto done;
360
361 Status = NetUserGetGroups(NULL,
362 lpUserName,
363 0,
364 (LPBYTE*)&pGroupInfo,
365 MAX_PREFERRED_LENGTH,
366 &dwGroupRead,
367 &dwGroupTotal);
368 if (Status != NERR_Success)
369 goto done;
370
371 PrintPaddedMessageString(4411, nPaddedLength);
372 ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_name);
373
374 PrintPaddedMessageString(4412, nPaddedLength);
375 ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_full_name);
376
377 PrintPaddedMessageString(4413, nPaddedLength);
378 ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_comment);
379
380 PrintPaddedMessageString(4414, nPaddedLength);
381 ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_usr_comment);
382
383 PrintPaddedMessageString(4416, nPaddedLength);
384 GetCountryFromCountryCode(pUserInfo->usri4_country_code,
385 ARRAYSIZE(szCountry), szCountry);
386 ConPrintf(StdOut, L"%03ld (%s)\n", pUserInfo->usri4_country_code, szCountry);
387
388 PrintPaddedMessageString(4419, nPaddedLength);
389 if (pUserInfo->usri4_flags & UF_ACCOUNTDISABLE)
390 PrintMessageString(4301);
391 else if (pUserInfo->usri4_flags & UF_LOCKOUT)
392 PrintMessageString(4440);
393 else
394 PrintMessageString(4300);
395 ConPuts(StdOut, L"\n");
396
397 PrintPaddedMessageString(4420, nPaddedLength);
398 if (pUserInfo->usri4_acct_expires == TIMEQ_FOREVER)
399 PrintMessageString(4305);
400 else
401 PrintDateTime(pUserInfo->usri4_acct_expires);
402 ConPuts(StdOut, L"\n\n");
403
404 PrintPaddedMessageString(4421, nPaddedLength);
405 dwLastSet = GetTimeInSeconds() - pUserInfo->usri4_password_age;
406 PrintDateTime(dwLastSet);
407 ConPuts(StdOut, L"\n");
408
409 PrintPaddedMessageString(4422, nPaddedLength);
410 if ((pUserInfo->usri4_flags & UF_DONT_EXPIRE_PASSWD) || pUserModals->usrmod0_max_passwd_age == TIMEQ_FOREVER)
411 PrintMessageString(4305);
412 else
413 PrintDateTime(dwLastSet + pUserModals->usrmod0_max_passwd_age);
414 ConPuts(StdOut, L"\n");
415
416 PrintPaddedMessageString(4423, nPaddedLength);
417 PrintDateTime(dwLastSet + pUserModals->usrmod0_min_passwd_age);
418 ConPuts(StdOut, L"\n");
419
420 PrintPaddedMessageString(4437, nPaddedLength);
421 PrintMessageString((pUserInfo->usri4_flags & UF_PASSWD_NOTREQD) ? 4301 : 4300);
422 ConPuts(StdOut, L"\n");
423
424 PrintPaddedMessageString(4438, nPaddedLength);
425 PrintMessageString((pUserInfo->usri4_flags & UF_PASSWD_CANT_CHANGE) ? 4301 : 4300);
426 ConPuts(StdOut, L"\n\n");
427
428 PrintPaddedMessageString(4424, nPaddedLength);
429 if (pUserInfo->usri4_workstations == NULL || wcslen(pUserInfo->usri4_workstations) == 0)
430 PrintMessageString(4302);
431 else
432 ConPrintf(StdOut, L"%s", pUserInfo->usri4_workstations);
433 ConPuts(StdOut, L"\n");
434
435 PrintPaddedMessageString(4429, nPaddedLength);
436 ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_script_path);
437
438 PrintPaddedMessageString(4439, nPaddedLength);
439 ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_profile);
440
441 PrintPaddedMessageString(4436, nPaddedLength);
442 ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_home_dir);
443
444 PrintPaddedMessageString(4430, nPaddedLength);
445 if (pUserInfo->usri4_last_logon == 0)
446 PrintMessageString(4305);
447 else
448 PrintDateTime(pUserInfo->usri4_last_logon);
449 ConPuts(StdOut, L"\n\n");
450
451 PrintPaddedMessageString(4432, nPaddedLength);
452 if (pUserInfo->usri4_logon_hours == NULL)
453 {
454 PrintMessageString(4302);
455 ConPuts(StdOut, L"\n");
456 }
457 else
458 {
459 PrintLogonHours(pUserInfo->usri4_units_per_week,
460 pUserInfo->usri4_logon_hours,
461 nPaddedLength);
462 }
463
464 ConPuts(StdOut, L"\n");
465 PrintPaddedMessageString(4427, nPaddedLength);
466 if (dwLocalGroupTotal != 0 && pLocalGroupInfo != NULL)
467 {
468 for (i = 0; i < dwLocalGroupTotal; i++)
469 {
470 if (i != 0)
471 PrintPadding(L' ', nPaddedLength);
472 ConPrintf(StdOut, L"*%s\n", pLocalGroupInfo[i].lgrui0_name);
473 }
474 }
475 else
476 {
477 ConPuts(StdOut, L"\n");
478 }
479
480 PrintPaddedMessageString(4431, nPaddedLength);
481 if (dwGroupTotal != 0 && pGroupInfo != NULL)
482 {
483 for (i = 0; i < dwGroupTotal; i++)
484 {
485 if (i != 0)
486 PrintPadding(L' ', nPaddedLength);
487 ConPrintf(StdOut, L"*%s\n", pGroupInfo[i].grui0_name);
488 }
489 }
490 else
491 {
492 ConPuts(StdOut, L"\n");
493 }
494
495 done:
496 if (pGroupInfo != NULL)
497 NetApiBufferFree(pGroupInfo);
498
499 if (pLocalGroupInfo != NULL)
500 NetApiBufferFree(pLocalGroupInfo);
501
502 if (pUserModals != NULL)
503 NetApiBufferFree(pUserModals);
504
505 if (pUserInfo != NULL)
506 NetApiBufferFree(pUserInfo);
507
508 return NERR_Success;
509 }
510
511
512 static
513 VOID
514 ReadPassword(
515 LPWSTR *lpPassword,
516 LPBOOL lpAllocated)
517 {
518 WCHAR szPassword1[PWLEN + 1];
519 WCHAR szPassword2[PWLEN + 1];
520 LPWSTR ptr;
521
522 *lpAllocated = FALSE;
523
524 while (TRUE)
525 {
526 PrintMessageString(4358);
527 ReadFromConsole(szPassword1, PWLEN + 1, FALSE);
528 ConPuts(StdOut, L"\n");
529
530 PrintMessageString(4361);
531 ReadFromConsole(szPassword2, PWLEN + 1, FALSE);
532 ConPuts(StdOut, L"\n");
533
534 if (wcslen(szPassword1) == wcslen(szPassword2) &&
535 wcscmp(szPassword1, szPassword2) == 0)
536 {
537 ptr = HeapAlloc(GetProcessHeap(),
538 0,
539 (wcslen(szPassword1) + 1) * sizeof(WCHAR));
540 if (ptr != NULL)
541 {
542 wcscpy(ptr, szPassword1);
543 *lpPassword = ptr;
544 *lpAllocated = TRUE;
545 return;
546 }
547 }
548 else
549 {
550 ConPuts(StdOut, L"\n");
551 PrintMessageString(3728);
552 *lpPassword = NULL;
553 }
554 }
555 }
556
557
558 static
559 VOID
560 GenerateRandomPassword(
561 LPWSTR *lpPassword,
562 LPBOOL lpAllocated)
563 {
564 LPWSTR pPassword = NULL;
565 INT nCharsLen, i, nLength = 8;
566
567 srand(GetTickCount());
568
569 pPassword = HeapAlloc(GetProcessHeap(),
570 HEAP_ZERO_MEMORY,
571 (nLength + 1) * sizeof(WCHAR));
572 if (pPassword == NULL)
573 return;
574
575 nCharsLen = wcslen(szPasswordChars);
576
577 for (i = 0; i < nLength; i++)
578 {
579 pPassword[i] = szPasswordChars[rand() % nCharsLen];
580 }
581
582 *lpPassword = pPassword;
583 *lpAllocated = TRUE;
584 }
585
586
587 static
588 NET_API_STATUS
589 BuildWorkstationsList(
590 _Out_ PWSTR *pWorkstationsList,
591 _In_ PWSTR pRaw)
592 {
593 BOOL isLastSep, isSep;
594 INT i, j;
595 WCHAR c;
596 INT nLength = 0;
597 INT nArgs = 0;
598 INT nRawLength;
599 PWSTR pList;
600
601 /* Check for invalid characters in the raw string */
602 if (wcspbrk(pRaw, L"/[]=?\\+:.") != NULL)
603 return 3952;
604
605 /* Count the number of workstations in the list and
606 * the required buffer size */
607 isLastSep = FALSE;
608 isSep = FALSE;
609 nRawLength = wcslen(pRaw);
610 for (i = 0; i < nRawLength; i++)
611 {
612 c = pRaw[i];
613 if (c == L',' || c == L';')
614 isSep = TRUE;
615
616 if (isSep == TRUE)
617 {
618 if ((isLastSep == FALSE) && (i != 0) && (i != nRawLength - 1))
619 nLength++;
620 }
621 else
622 {
623 nLength++;
624
625 if (isLastSep == TRUE || (isLastSep == FALSE && i == 0))
626 nArgs++;
627 }
628
629 isLastSep = isSep;
630 isSep = FALSE;
631 }
632
633 nLength++;
634
635 /* Leave, if there are no workstations in the list */
636 if (nArgs == 0)
637 {
638 pWorkstationsList = NULL;
639 return NERR_Success;
640 }
641
642 /* Fail if there are more than eight workstations in the list */
643 if (nArgs > 8)
644 return 3951;
645
646 /* Allocate the buffer for the clean workstation list */
647 pList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nLength * sizeof(WCHAR));
648 if (pList == NULL)
649 return ERROR_NOT_ENOUGH_MEMORY;
650
651 /* Build the clean workstation list */
652 isLastSep = FALSE;
653 isSep = FALSE;
654 nRawLength = wcslen(pRaw);
655 for (i = 0, j = 0; i < nRawLength; i++)
656 {
657 c = pRaw[i];
658 if (c == L',' || c == L';')
659 isSep = TRUE;
660
661 if (isSep == TRUE)
662 {
663 if ((isLastSep == FALSE) && (i != 0) && (i != nRawLength - 1))
664 {
665 pList[j] = L',';
666 j++;
667 }
668 }
669 else
670 {
671 pList[j] = c;
672 j++;
673
674 if (isLastSep == TRUE || (isLastSep == FALSE && i == 0))
675 nArgs++;
676 }
677
678 isLastSep = isSep;
679 isSep = FALSE;
680 }
681
682 *pWorkstationsList = pList;
683
684 return NERR_Success;
685 }
686
687
688 static
689 BOOL
690 ReadNumber(
691 PWSTR *s,
692 PWORD pwValue)
693 {
694 if (!iswdigit(**s))
695 return FALSE;
696
697 while (iswdigit(**s))
698 {
699 *pwValue = *pwValue * 10 + **s - L'0';
700 (*s)++;
701 }
702
703 return TRUE;
704 }
705
706
707 static
708 BOOL
709 ReadSeparator(
710 PWSTR *s)
711 {
712 if (**s == L'/' || **s == L'.')
713 {
714 (*s)++;
715 return TRUE;
716 }
717
718 return FALSE;
719 }
720
721
722 static
723 BOOL
724 ParseDate(
725 PWSTR s,
726 PULONG pSeconds)
727 {
728 SYSTEMTIME SystemTime = {0};
729 FILETIME LocalFileTime, FileTime;
730 LARGE_INTEGER Time;
731 INT nDateFormat = 0;
732 PWSTR p = s;
733
734 if (!*s)
735 return FALSE;
736
737 GetLocaleInfoW(LOCALE_USER_DEFAULT,
738 LOCALE_IDATE,
739 (PWSTR)&nDateFormat,
740 sizeof(INT));
741
742 switch (nDateFormat)
743 {
744 case 0: /* mmddyy */
745 default:
746 if (!ReadNumber(&p, &SystemTime.wMonth))
747 return FALSE;
748 if (!ReadSeparator(&p))
749 return FALSE;
750 if (!ReadNumber(&p, &SystemTime.wDay))
751 return FALSE;
752 if (!ReadSeparator(&p))
753 return FALSE;
754 if (!ReadNumber(&p, &SystemTime.wYear))
755 return FALSE;
756 break;
757
758 case 1: /* ddmmyy */
759 if (!ReadNumber(&p, &SystemTime.wDay))
760 return FALSE;
761 if (!ReadSeparator(&p))
762 return FALSE;
763 if (!ReadNumber(&p, &SystemTime.wMonth))
764 return FALSE;
765 if (!ReadSeparator(&p))
766 return FALSE;
767 if (!ReadNumber(&p, &SystemTime.wYear))
768 return FALSE;
769 break;
770
771 case 2: /* yymmdd */
772 if (!ReadNumber(&p, &SystemTime.wYear))
773 return FALSE;
774 if (!ReadSeparator(&p))
775 return FALSE;
776 if (!ReadNumber(&p, &SystemTime.wMonth))
777 return FALSE;
778 if (!ReadSeparator(&p))
779 return FALSE;
780 if (!ReadNumber(&p, &SystemTime.wDay))
781 return FALSE;
782 break;
783 }
784
785 /* if only entered two digits: */
786 /* assume 2000's if value less than 80 */
787 /* assume 1900's if value greater or equal 80 */
788 if (SystemTime.wYear <= 99)
789 {
790 if (SystemTime.wYear >= 80)
791 SystemTime.wYear += 1900;
792 else
793 SystemTime.wYear += 2000;
794 }
795
796 if (!SystemTimeToFileTime(&SystemTime, &LocalFileTime))
797 return FALSE;
798
799 if (!LocalFileTimeToFileTime(&LocalFileTime, &FileTime))
800 return FALSE;
801
802 Time.u.LowPart = FileTime.dwLowDateTime;
803 Time.u.HighPart = FileTime.dwHighDateTime;
804
805 if (!RtlTimeToSecondsSince1970(&Time, pSeconds))
806 return FALSE;
807
808 return TRUE;
809 }
810
811
812 static
813 DWORD
814 ParseLogonHours(
815 PWSTR pszParams,
816 PBYTE *ppLogonHours,
817 PDWORD pdwUnitsPerWeek)
818 {
819 PBYTE pLogonHours = NULL;
820 DWORD dwError = ERROR_SUCCESS;
821
822 pLogonHours = HeapAlloc(GetProcessHeap(),
823 HEAP_ZERO_MEMORY,
824 UNITS_PER_WEEK / 8);
825 if (pLogonHours == NULL)
826 return ERROR_OUTOFMEMORY;
827
828 if (*pszParams == UNICODE_NULL)
829 {
830 goto done;
831 }
832
833 if (wcsicmp(pszParams, L"all") == 0)
834 {
835 FillMemory(pLogonHours, UNITS_PER_WEEK / 8, 0xFF);
836 goto done;
837 }
838
839 /* FIXME */
840 /* Mockup error because we do not parse the line yet */
841 dwError = 3768;
842
843 done:
844 if (dwError == ERROR_SUCCESS)
845 {
846 *ppLogonHours = pLogonHours;
847 *pdwUnitsPerWeek = UNITS_PER_WEEK;
848 }
849 else
850 {
851 if (pLogonHours != NULL)
852 HeapFree(GetProcessHeap(), 0, pLogonHours);
853 }
854
855 return dwError;
856 }
857
858
859 INT
860 cmdUser(
861 INT argc,
862 WCHAR **argv)
863 {
864 INT i, j;
865 INT result = 0;
866 BOOL bAdd = FALSE;
867 BOOL bDelete = FALSE;
868 #if 0
869 BOOL bDomain = FALSE;
870 #endif
871 BOOL bRandomPassword = FALSE;
872 LPWSTR lpUserName = NULL;
873 LPWSTR lpPassword = NULL;
874 PUSER_INFO_4 pUserInfo = NULL;
875 USER_INFO_4 UserInfo;
876 LPWSTR pWorkstations = NULL;
877 LPWSTR p;
878 LPWSTR endptr;
879 DWORD value;
880 BOOL bPasswordAllocated = FALSE;
881 PBYTE pLogonHours = NULL;
882 DWORD dwUnitsPerWeek;
883 NET_API_STATUS Status;
884
885 i = 2;
886 if ((i < argc) && (argv[i][0] != L'/'))
887 {
888 lpUserName = argv[i];
889 // ConPrintf(StdOut, L"User: %s\n", lpUserName);
890 i++;
891 }
892
893 if ((i < argc) && (argv[i][0] != L'/'))
894 {
895 lpPassword = argv[i];
896 // ConPrintf(StdOut, L"Password: %s\n", lpPassword);
897 i++;
898 }
899
900 for (j = i; j < argc; j++)
901 {
902 if (_wcsicmp(argv[j], L"/help") == 0)
903 {
904 PrintNetMessage(MSG_USER_HELP);
905 return 0;
906 }
907 else if (_wcsicmp(argv[j], L"/add") == 0)
908 {
909 bAdd = TRUE;
910 }
911 else if (_wcsicmp(argv[j], L"/delete") == 0)
912 {
913 bDelete = TRUE;
914 }
915 else if (_wcsicmp(argv[j], L"/domain") == 0)
916 {
917 ConPuts(StdErr, L"The /DOMAIN option is not supported yet.\n");
918 #if 0
919 bDomain = TRUE;
920 #endif
921 }
922 else if (_wcsicmp(argv[j], L"/random") == 0)
923 {
924 bRandomPassword = TRUE;
925 GenerateRandomPassword(&lpPassword,
926 &bPasswordAllocated);
927 }
928 }
929
930 if (lpUserName == NULL && lpPassword == NULL)
931 {
932 Status = EnumerateUsers();
933 ConPrintf(StdOut, L"Status: %lu\n", Status);
934 return 0;
935 }
936 else if (lpUserName != NULL && lpPassword == NULL && argc == 3)
937 {
938 Status = DisplayUser(lpUserName);
939 ConPrintf(StdOut, L"Status: %lu\n", Status);
940 return 0;
941 }
942
943 if (bAdd && bDelete)
944 {
945 result = 1;
946 goto done;
947 }
948
949 /* Interactive password input */
950 if (lpPassword != NULL && wcscmp(lpPassword, L"*") == 0)
951 {
952 ReadPassword(&lpPassword,
953 &bPasswordAllocated);
954 }
955
956 if (!bAdd && !bDelete)
957 {
958 /* Modify the user */
959 Status = NetUserGetInfo(NULL,
960 lpUserName,
961 4,
962 (LPBYTE*)&pUserInfo);
963 if (Status != NERR_Success)
964 {
965 ConPrintf(StdOut, L"Status: %lu\n", Status);
966 result = 1;
967 goto done;
968 }
969 }
970 else if (bAdd && !bDelete)
971 {
972 /* Add the user */
973 ZeroMemory(&UserInfo, sizeof(USER_INFO_4));
974
975 UserInfo.usri4_name = lpUserName;
976 UserInfo.usri4_password = lpPassword;
977 UserInfo.usri4_flags = UF_SCRIPT | UF_NORMAL_ACCOUNT;
978 UserInfo.usri4_acct_expires = TIMEQ_FOREVER;
979 UserInfo.usri4_primary_group_id = DOMAIN_GROUP_RID_USERS;
980
981 pUserInfo = &UserInfo;
982 }
983
984 for (j = i; j < argc; j++)
985 {
986 if (_wcsnicmp(argv[j], L"/active:", 8) == 0)
987 {
988 p = &argv[i][8];
989 if (_wcsicmp(p, L"yes") == 0)
990 {
991 pUserInfo->usri4_flags &= ~UF_ACCOUNTDISABLE;
992 }
993 else if (_wcsicmp(p, L"no") == 0)
994 {
995 pUserInfo->usri4_flags |= UF_ACCOUNTDISABLE;
996 }
997 else
998 {
999 PrintMessageStringV(3952, L"/ACTIVE");
1000 result = 1;
1001 goto done;
1002 }
1003 }
1004 else if (_wcsnicmp(argv[j], L"/comment:", 9) == 0)
1005 {
1006 pUserInfo->usri4_comment = &argv[j][9];
1007 }
1008 else if (_wcsnicmp(argv[j], L"/countrycode:", 13) == 0)
1009 {
1010 p = &argv[i][13];
1011 value = wcstoul(p, &endptr, 10);
1012 if (*endptr != 0)
1013 {
1014 PrintMessageStringV(3952, L"/COUNTRYCODE");
1015 result = 1;
1016 goto done;
1017 }
1018
1019 /* Verify the country code */
1020 if (GetCountryFromCountryCode(value, 0, NULL))
1021 pUserInfo->usri4_country_code = value;
1022 }
1023 else if (_wcsnicmp(argv[j], L"/expires:", 9) == 0)
1024 {
1025 p = &argv[i][9];
1026 if (_wcsicmp(p, L"never") == 0)
1027 {
1028 pUserInfo->usri4_acct_expires = TIMEQ_FOREVER;
1029 }
1030 else if (!ParseDate(p, &pUserInfo->usri4_acct_expires))
1031 {
1032 PrintMessageStringV(3952, L"/EXPIRES");
1033 result = 1;
1034 goto done;
1035 }
1036 }
1037 else if (_wcsnicmp(argv[j], L"/fullname:", 10) == 0)
1038 {
1039 pUserInfo->usri4_full_name = &argv[j][10];
1040 }
1041 else if (_wcsnicmp(argv[j], L"/homedir:", 9) == 0)
1042 {
1043 pUserInfo->usri4_home_dir = &argv[j][9];
1044 }
1045 else if (_wcsnicmp(argv[j], L"/passwordchg:", 13) == 0)
1046 {
1047 p = &argv[i][13];
1048 if (_wcsicmp(p, L"yes") == 0)
1049 {
1050 pUserInfo->usri4_flags &= ~UF_PASSWD_CANT_CHANGE;
1051 }
1052 else if (_wcsicmp(p, L"no") == 0)
1053 {
1054 pUserInfo->usri4_flags |= UF_PASSWD_CANT_CHANGE;
1055 }
1056 else
1057 {
1058 PrintMessageStringV(3952, L"/PASSWORDCHG");
1059 result = 1;
1060 goto done;
1061 }
1062 }
1063 else if (_wcsnicmp(argv[j], L"/passwordreq:", 13) == 0)
1064 {
1065 p = &argv[i][13];
1066 if (_wcsicmp(p, L"yes") == 0)
1067 {
1068 pUserInfo->usri4_flags &= ~UF_PASSWD_NOTREQD;
1069 }
1070 else if (_wcsicmp(p, L"no") == 0)
1071 {
1072 pUserInfo->usri4_flags |= UF_PASSWD_NOTREQD;
1073 }
1074 else
1075 {
1076 PrintMessageStringV(3952, L"/PASSWORDREQ");
1077 result = 1;
1078 goto done;
1079 }
1080 }
1081 else if (_wcsnicmp(argv[j], L"/profilepath:", 13) == 0)
1082 {
1083 pUserInfo->usri4_profile = &argv[j][13];
1084 }
1085 else if (_wcsnicmp(argv[j], L"/scriptpath:", 12) == 0)
1086 {
1087 pUserInfo->usri4_script_path = &argv[j][12];
1088 }
1089 else if (_wcsnicmp(argv[j], L"/times:", 7) == 0)
1090 {
1091 Status = ParseLogonHours(&argv[j][7],
1092 &pLogonHours,
1093 &dwUnitsPerWeek);
1094 if (Status == ERROR_SUCCESS)
1095 {
1096 pUserInfo->usri4_logon_hours = pLogonHours;
1097 pUserInfo->usri4_units_per_week = dwUnitsPerWeek;
1098 }
1099 else
1100 {
1101 PrintMessageString(Status);
1102 goto done;
1103 }
1104 }
1105 else if (_wcsnicmp(argv[j], L"/usercomment:", 13) == 0)
1106 {
1107 pUserInfo->usri4_usr_comment = &argv[j][13];
1108 }
1109 else if (_wcsnicmp(argv[j], L"/workstations:", 14) == 0)
1110 {
1111 p = &argv[i][14];
1112 if (wcscmp(p, L"*") == 0 || wcscmp(p, L"") == 0)
1113 {
1114 pUserInfo->usri4_workstations = NULL;
1115 }
1116 else
1117 {
1118 Status = BuildWorkstationsList(&pWorkstations, p);
1119 if (Status == NERR_Success)
1120 {
1121 pUserInfo->usri4_workstations = pWorkstations;
1122 }
1123 else
1124 {
1125 ConPrintf(StdOut, L"Status %lu\n\n", Status);
1126 result = 1;
1127 goto done;
1128 }
1129 }
1130 }
1131 }
1132
1133 if (!bAdd && !bDelete)
1134 {
1135 /* Modify the user */
1136 Status = NetUserSetInfo(NULL,
1137 lpUserName,
1138 4,
1139 (LPBYTE)pUserInfo,
1140 NULL);
1141 ConPrintf(StdOut, L"Status: %lu\n", Status);
1142 }
1143 else if (bAdd && !bDelete)
1144 {
1145 /* Add the user */
1146 Status = NetUserAdd(NULL,
1147 4,
1148 (LPBYTE)pUserInfo,
1149 NULL);
1150 ConPrintf(StdOut, L"Status: %lu\n", Status);
1151 }
1152 else if (!bAdd && bDelete)
1153 {
1154 /* Delete the user */
1155 Status = NetUserDel(NULL,
1156 lpUserName);
1157 ConPrintf(StdOut, L"Status: %lu\n", Status);
1158 }
1159
1160 if (Status == NERR_Success &&
1161 lpPassword != NULL &&
1162 bRandomPassword == TRUE)
1163 {
1164 PrintMessageStringV(3968, lpUserName, lpPassword);
1165 }
1166
1167 done:
1168 if (pLogonHours != NULL)
1169 HeapFree(GetProcessHeap(), 0, pLogonHours);
1170
1171 if (pWorkstations != NULL)
1172 HeapFree(GetProcessHeap(), 0, pWorkstations);
1173
1174 if ((bPasswordAllocated == TRUE) && (lpPassword != NULL))
1175 HeapFree(GetProcessHeap(), 0, lpPassword);
1176
1177 if (!bAdd && !bDelete && pUserInfo != NULL)
1178 NetApiBufferFree(pUserInfo);
1179
1180 if (result != 0)
1181 {
1182 PrintMessageString(4381);
1183 ConPuts(StdOut, L"\n");
1184 PrintNetMessage(MSG_USER_SYNTAX);
1185 }
1186
1187 return result;
1188 }
1189
1190 /* EOF */