2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS net command
4 * FILE: base/applications/network/net/cmdUser.c
7 * PROGRAMMERS: Eric Kohl
13 #define SECONDS_PER_DAY (60 * 60 * 24)
14 #define SECONDS_PER_HOUR (60 * 60)
15 #define HOURS_PER_DAY 24
16 #define DAYS_PER_WEEK 7
18 typedef struct _COUNTY_TABLE
22 } COUNTRY_TABLE
, *PCOUNTRY_TABLE
;
25 static WCHAR szPasswordChars
[] = L
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@#$%_-+:";
26 static COUNTRY_TABLE CountryTable
[] =
27 { { 0, 5080}, // System Default
28 { 1, 5081}, // United States
29 { 2, 5082}, // Canada (French)
30 { 3, 5083}, // Latin America
31 { 31, 5084}, // Netherlands
32 { 32, 5085}, // Belgium
33 { 33, 5086}, // France
36 { 41, 5088}, // Switzerland
37 { 44, 5089}, // United Kingdom
38 { 45, 5091}, // Denmark
39 { 46, 5092}, // Sweden
40 { 47, 5093}, // Norway
41 { 49, 5094}, // Germany
42 { 61, 5095}, // Australia
45 { 86, 5098}, // China (PRC)
46 { 88, 5099}, // Taiwan
48 {351, 5101}, // Portugal
49 {358, 5102}, // Finland
50 {785, 5103}, // Arabic
51 {972, 5104} }; // Hebrew
56 CompareInfo(const void *a
, const void *b
)
58 return _wcsicmp(((PUSER_INFO_0
)a
)->usri0_name
,
59 ((PUSER_INFO_0
)b
)->usri0_name
);
67 PUSER_INFO_0 pBuffer
= NULL
;
68 PSERVER_INFO_100 pServer
= NULL
;
69 DWORD dwRead
= 0, dwTotal
= 0;
71 DWORD ResumeHandle
= 0;
72 NET_API_STATUS Status
;
74 Status
= NetServerGetInfo(NULL
,
77 if (Status
!= NERR_Success
)
80 ConPuts(StdOut
, L
"\n");
81 PrintMessageStringV(4410, pServer
->sv100_name
);
82 ConPuts(StdOut
, L
"\n");
83 PrintPadding(L
'-', 79);
84 ConPuts(StdOut
, L
"\n");
86 NetApiBufferFree(pServer
);
90 Status
= NetUserEnum(NULL
,
98 if ((Status
!= NERR_Success
) && (Status
!= ERROR_MORE_DATA
))
103 sizeof(PUSER_INFO_0
),
106 for (i
= 0; i
< dwRead
; i
++)
108 if (pBuffer
[i
].usri0_name
)
109 ConPrintf(StdOut
, L
"%s\n", pBuffer
[i
].usri0_name
);
112 NetApiBufferFree(pBuffer
);
115 while (Status
== ERROR_MORE_DATA
);
123 PrintDateTime(DWORD dwSeconds
)
127 SYSTEMTIME SystemTime
;
128 WCHAR DateBuffer
[80];
129 WCHAR TimeBuffer
[80];
131 RtlSecondsSince1970ToTime(dwSeconds
, &Time
);
132 FileTime
.dwLowDateTime
= Time
.u
.LowPart
;
133 FileTime
.dwHighDateTime
= Time
.u
.HighPart
;
134 FileTimeToLocalFileTime(&FileTime
, &FileTime
);
135 FileTimeToSystemTime(&FileTime
, &SystemTime
);
137 GetDateFormatW(LOCALE_USER_DEFAULT
,
142 ARRAYSIZE(DateBuffer
));
144 GetTimeFormatW(LOCALE_USER_DEFAULT
,
149 ARRAYSIZE(TimeBuffer
));
151 ConPrintf(StdOut
, L
"%s %s", DateBuffer
, TimeBuffer
);
157 PrintLocalTime(DWORD dwSeconds
)
161 SYSTEMTIME SystemTime
;
162 WCHAR TimeBuffer
[80];
164 RtlSecondsSince1970ToTime(dwSeconds
, &Time
);
165 FileTime
.dwLowDateTime
= Time
.u
.LowPart
;
166 FileTime
.dwHighDateTime
= Time
.u
.HighPart
;
167 FileTimeToSystemTime(&FileTime
, &SystemTime
);
169 GetTimeFormatW(LOCALE_USER_DEFAULT
,
174 ARRAYSIZE(TimeBuffer
));
176 ConPrintf(StdOut
, L
"%s", TimeBuffer
);
182 GetTimeInSeconds(VOID
)
188 GetSystemTimeAsFileTime(&FileTime
);
189 Time
.u
.LowPart
= FileTime
.dwLowDateTime
;
190 Time
.u
.HighPart
= FileTime
.dwHighDateTime
;
191 RtlTimeToSecondsSince1970(&Time
, &dwSeconds
);
199 GetCountryFromCountryCode(
200 _In_ DWORD dwCountryCode
,
201 _In_ DWORD dwCountryLength
,
202 _Out_ PWSTR szCountryBuffer
)
206 for (i
= 0; i
< ARRAYSIZE(CountryTable
); i
++)
208 if (CountryTable
[i
].dwCountryCode
== dwCountryCode
)
210 if (szCountryBuffer
!= NULL
&& dwCountryLength
> 0)
212 FormatMessageW(FORMAT_MESSAGE_FROM_HMODULE
| FORMAT_MESSAGE_IGNORE_INSERTS
,
214 CountryTable
[i
].dwMessageId
,
235 DWORD dwIndex
= dwBitNumber
/ 8;
236 BYTE Mask
= 1 << (dwBitNumber
& 7);
238 return ((pBitmap
[dwIndex
] & Mask
) != 0);
248 DWORD dwIndex
= dwBitNumber
/ 8;
249 BYTE Mask
= 1 << (dwBitNumber
& 7);
251 pBitmap
[dwIndex
] |= Mask
;
258 DWORD dwUnitsPerWeek
,
262 DWORD dwUnitsPerDay
, dwBitNumber
, dwSecondsPerUnit
;
263 DWORD dwStartTime
, dwEndTime
, dwStartDay
, dwEndDay
, dwBias
;
264 BOOL bBitValue
, bFirst
= TRUE
;
265 TIME_ZONE_INFORMATION TimeZoneInformation
;
267 GetTimeZoneInformation(&TimeZoneInformation
);
268 dwBias
= (TimeZoneInformation
.Bias
/ 60) * SECONDS_PER_HOUR
;
270 if ((dwUnitsPerWeek
== 0) ||
271 ((dwUnitsPerWeek
%7) != 0))
274 dwUnitsPerDay
= dwUnitsPerWeek
/ 7;
276 if (((dwUnitsPerDay
% 24) != 0) ||
277 ((dwUnitsPerDay
/ 24) > 6))
280 dwSecondsPerUnit
= (SECONDS_PER_DAY
) / dwUnitsPerDay
;
282 for (dwBitNumber
= 0; dwBitNumber
< dwUnitsPerWeek
; dwBitNumber
++)
284 bBitValue
= GetBitValue(pLogonHours
, dwBitNumber
);
287 dwStartTime
= dwSecondsPerUnit
* dwBitNumber
;
289 while (bBitValue
!= 0 && dwBitNumber
< dwUnitsPerWeek
)
292 if (dwBitNumber
< dwUnitsPerWeek
)
293 bBitValue
= GetBitValue(pLogonHours
, dwBitNumber
);
296 dwEndTime
= dwSecondsPerUnit
* dwBitNumber
;
299 PrintPadding(L
' ', nPaddedLength
);
301 if (dwStartTime
== 0 && dwEndTime
== (SECONDS_PER_DAY
* 7))
303 PrintMessageString(4302);
304 ConPuts(StdOut
, L
"\n");
308 dwStartDay
= dwStartTime
/ SECONDS_PER_DAY
;
309 dwEndDay
= (dwEndTime
/ SECONDS_PER_DAY
) % 7;
311 PrintMessageString(4307 + dwStartDay
);
312 ConPuts(StdOut
, L
" ");
314 /* Convert from GMT to local timezone */
315 PrintLocalTime((dwStartTime
% SECONDS_PER_DAY
) - dwBias
);
317 ConPrintf(StdOut
, L
" - ");
318 if (dwStartDay
!= dwEndDay
)
320 PrintMessageString(4307 + dwEndDay
);
321 ConPuts(StdOut
, L
" ");
324 /* Convert from GMT to local timezone */
325 PrintLocalTime((dwEndTime
% SECONDS_PER_DAY
) - dwBias
);
326 ConPuts(StdOut
, L
"\n");
336 PrintMessageString(4434);
337 ConPuts(StdOut
, L
"\n");
344 DisplayUser(LPWSTR lpUserName
)
346 PUSER_MODALS_INFO_0 pUserModals
= NULL
;
347 PUSER_INFO_4 pUserInfo
= NULL
;
348 PLOCALGROUP_USERS_INFO_0 pLocalGroupInfo
= NULL
;
349 PGROUP_USERS_INFO_0 pGroupInfo
= NULL
;
350 DWORD dwLocalGroupRead
, dwLocalGroupTotal
;
351 DWORD dwGroupRead
, dwGroupTotal
;
355 INT nPaddedLength
= 36;
356 NET_API_STATUS Status
;
358 /* Modify the user */
359 Status
= NetUserGetInfo(NULL
,
362 (LPBYTE
*)&pUserInfo
);
363 if (Status
!= NERR_Success
)
366 Status
= NetUserModalsGet(NULL
,
368 (LPBYTE
*)&pUserModals
);
369 if (Status
!= NERR_Success
)
372 Status
= NetUserGetLocalGroups(NULL
,
376 (LPBYTE
*)&pLocalGroupInfo
,
377 MAX_PREFERRED_LENGTH
,
380 if (Status
!= NERR_Success
)
383 Status
= NetUserGetGroups(NULL
,
386 (LPBYTE
*)&pGroupInfo
,
387 MAX_PREFERRED_LENGTH
,
390 if (Status
!= NERR_Success
)
393 PrintPaddedMessageString(4411, nPaddedLength
);
394 ConPrintf(StdOut
, L
"%s\n", pUserInfo
->usri4_name
);
396 PrintPaddedMessageString(4412, nPaddedLength
);
397 ConPrintf(StdOut
, L
"%s\n", pUserInfo
->usri4_full_name
);
399 PrintPaddedMessageString(4413, nPaddedLength
);
400 ConPrintf(StdOut
, L
"%s\n", pUserInfo
->usri4_comment
);
402 PrintPaddedMessageString(4414, nPaddedLength
);
403 ConPrintf(StdOut
, L
"%s\n", pUserInfo
->usri4_usr_comment
);
405 PrintPaddedMessageString(4416, nPaddedLength
);
406 GetCountryFromCountryCode(pUserInfo
->usri4_country_code
,
407 ARRAYSIZE(szCountry
), szCountry
);
408 ConPrintf(StdOut
, L
"%03ld (%s)\n", pUserInfo
->usri4_country_code
, szCountry
);
410 PrintPaddedMessageString(4419, nPaddedLength
);
411 if (pUserInfo
->usri4_flags
& UF_ACCOUNTDISABLE
)
412 PrintMessageString(4301);
413 else if (pUserInfo
->usri4_flags
& UF_LOCKOUT
)
414 PrintMessageString(4440);
416 PrintMessageString(4300);
417 ConPuts(StdOut
, L
"\n");
419 PrintPaddedMessageString(4420, nPaddedLength
);
420 if (pUserInfo
->usri4_acct_expires
== TIMEQ_FOREVER
)
421 PrintMessageString(4305);
423 PrintDateTime(pUserInfo
->usri4_acct_expires
);
424 ConPuts(StdOut
, L
"\n\n");
426 PrintPaddedMessageString(4421, nPaddedLength
);
427 dwLastSet
= GetTimeInSeconds() - pUserInfo
->usri4_password_age
;
428 PrintDateTime(dwLastSet
);
429 ConPuts(StdOut
, L
"\n");
431 PrintPaddedMessageString(4422, nPaddedLength
);
432 if ((pUserInfo
->usri4_flags
& UF_DONT_EXPIRE_PASSWD
) || pUserModals
->usrmod0_max_passwd_age
== TIMEQ_FOREVER
)
433 PrintMessageString(4305);
435 PrintDateTime(dwLastSet
+ pUserModals
->usrmod0_max_passwd_age
);
436 ConPuts(StdOut
, L
"\n");
438 PrintPaddedMessageString(4423, nPaddedLength
);
439 PrintDateTime(dwLastSet
+ pUserModals
->usrmod0_min_passwd_age
);
440 ConPuts(StdOut
, L
"\n");
442 PrintPaddedMessageString(4437, nPaddedLength
);
443 PrintMessageString((pUserInfo
->usri4_flags
& UF_PASSWD_NOTREQD
) ? 4301 : 4300);
444 ConPuts(StdOut
, L
"\n");
446 PrintPaddedMessageString(4438, nPaddedLength
);
447 PrintMessageString((pUserInfo
->usri4_flags
& UF_PASSWD_CANT_CHANGE
) ? 4301 : 4300);
448 ConPuts(StdOut
, L
"\n\n");
450 PrintPaddedMessageString(4424, nPaddedLength
);
451 if (pUserInfo
->usri4_workstations
== NULL
|| wcslen(pUserInfo
->usri4_workstations
) == 0)
452 PrintMessageString(4302);
454 ConPrintf(StdOut
, L
"%s", pUserInfo
->usri4_workstations
);
455 ConPuts(StdOut
, L
"\n");
457 PrintPaddedMessageString(4429, nPaddedLength
);
458 ConPrintf(StdOut
, L
"%s\n", pUserInfo
->usri4_script_path
);
460 PrintPaddedMessageString(4439, nPaddedLength
);
461 ConPrintf(StdOut
, L
"%s\n", pUserInfo
->usri4_profile
);
463 PrintPaddedMessageString(4436, nPaddedLength
);
464 ConPrintf(StdOut
, L
"%s\n", pUserInfo
->usri4_home_dir
);
466 PrintPaddedMessageString(4430, nPaddedLength
);
467 if (pUserInfo
->usri4_last_logon
== 0)
468 PrintMessageString(4305);
470 PrintDateTime(pUserInfo
->usri4_last_logon
);
471 ConPuts(StdOut
, L
"\n\n");
473 PrintPaddedMessageString(4432, nPaddedLength
);
474 if (pUserInfo
->usri4_logon_hours
== NULL
)
476 PrintMessageString(4302);
477 ConPuts(StdOut
, L
"\n");
481 PrintLogonHours(pUserInfo
->usri4_units_per_week
,
482 pUserInfo
->usri4_logon_hours
,
486 ConPuts(StdOut
, L
"\n");
487 PrintPaddedMessageString(4427, nPaddedLength
);
488 if (dwLocalGroupTotal
!= 0 && pLocalGroupInfo
!= NULL
)
490 for (i
= 0; i
< dwLocalGroupTotal
; i
++)
493 PrintPadding(L
' ', nPaddedLength
);
494 ConPrintf(StdOut
, L
"*%s\n", pLocalGroupInfo
[i
].lgrui0_name
);
499 ConPuts(StdOut
, L
"\n");
502 PrintPaddedMessageString(4431, nPaddedLength
);
503 if (dwGroupTotal
!= 0 && pGroupInfo
!= NULL
)
505 for (i
= 0; i
< dwGroupTotal
; i
++)
508 PrintPadding(L
' ', nPaddedLength
);
509 ConPrintf(StdOut
, L
"*%s\n", pGroupInfo
[i
].grui0_name
);
514 ConPuts(StdOut
, L
"\n");
518 if (pGroupInfo
!= NULL
)
519 NetApiBufferFree(pGroupInfo
);
521 if (pLocalGroupInfo
!= NULL
)
522 NetApiBufferFree(pLocalGroupInfo
);
524 if (pUserModals
!= NULL
)
525 NetApiBufferFree(pUserModals
);
527 if (pUserInfo
!= NULL
)
528 NetApiBufferFree(pUserInfo
);
540 WCHAR szPassword1
[PWLEN
+ 1];
541 WCHAR szPassword2
[PWLEN
+ 1];
544 *lpAllocated
= FALSE
;
548 PrintMessageString(4358);
549 ReadFromConsole(szPassword1
, PWLEN
+ 1, FALSE
);
550 ConPuts(StdOut
, L
"\n");
552 PrintMessageString(4361);
553 ReadFromConsole(szPassword2
, PWLEN
+ 1, FALSE
);
554 ConPuts(StdOut
, L
"\n");
556 if (wcslen(szPassword1
) == wcslen(szPassword2
) &&
557 wcscmp(szPassword1
, szPassword2
) == 0)
559 ptr
= HeapAlloc(GetProcessHeap(),
561 (wcslen(szPassword1
) + 1) * sizeof(WCHAR
));
564 wcscpy(ptr
, szPassword1
);
572 ConPuts(StdOut
, L
"\n");
573 PrintMessageString(3728);
582 GenerateRandomPassword(
586 LPWSTR pPassword
= NULL
;
587 INT nCharsLen
, i
, nLength
= 8;
589 srand(GetTickCount());
591 pPassword
= HeapAlloc(GetProcessHeap(),
593 (nLength
+ 1) * sizeof(WCHAR
));
594 if (pPassword
== NULL
)
597 nCharsLen
= wcslen(szPasswordChars
);
599 for (i
= 0; i
< nLength
; i
++)
601 pPassword
[i
] = szPasswordChars
[rand() % nCharsLen
];
604 *lpPassword
= pPassword
;
611 BuildWorkstationsList(
612 _Out_ PWSTR
*pWorkstationsList
,
615 BOOL isLastSep
, isSep
;
623 /* Check for invalid characters in the raw string */
624 if (wcspbrk(pRaw
, L
"/[]=?\\+:.") != NULL
)
627 /* Count the number of workstations in the list and
628 * the required buffer size */
631 nRawLength
= wcslen(pRaw
);
632 for (i
= 0; i
< nRawLength
; i
++)
635 if (c
== L
',' || c
== L
';')
640 if ((isLastSep
== FALSE
) && (i
!= 0) && (i
!= nRawLength
- 1))
647 if (isLastSep
== TRUE
|| (isLastSep
== FALSE
&& i
== 0))
657 /* Leave, if there are no workstations in the list */
660 pWorkstationsList
= NULL
;
664 /* Fail if there are more than eight workstations in the list */
668 /* Allocate the buffer for the clean workstation list */
669 pList
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, nLength
* sizeof(WCHAR
));
671 return ERROR_NOT_ENOUGH_MEMORY
;
673 /* Build the clean workstation list */
676 nRawLength
= wcslen(pRaw
);
677 for (i
= 0, j
= 0; i
< nRawLength
; i
++)
680 if (c
== L
',' || c
== L
';')
685 if ((isLastSep
== FALSE
) && (i
!= 0) && (i
!= nRawLength
- 1))
696 if (isLastSep
== TRUE
|| (isLastSep
== FALSE
&& i
== 0))
704 *pWorkstationsList
= pList
;
719 while (iswdigit(**s
))
721 *pwValue
= *pwValue
* 10 + **s
- L
'0';
734 if (**s
== L
'/' || **s
== L
'.')
750 SYSTEMTIME SystemTime
= {0};
751 FILETIME LocalFileTime
, FileTime
;
759 GetLocaleInfoW(LOCALE_USER_DEFAULT
,
768 if (!ReadNumber(&p
, &SystemTime
.wMonth
))
770 if (!ReadSeparator(&p
))
772 if (!ReadNumber(&p
, &SystemTime
.wDay
))
774 if (!ReadSeparator(&p
))
776 if (!ReadNumber(&p
, &SystemTime
.wYear
))
781 if (!ReadNumber(&p
, &SystemTime
.wDay
))
783 if (!ReadSeparator(&p
))
785 if (!ReadNumber(&p
, &SystemTime
.wMonth
))
787 if (!ReadSeparator(&p
))
789 if (!ReadNumber(&p
, &SystemTime
.wYear
))
794 if (!ReadNumber(&p
, &SystemTime
.wYear
))
796 if (!ReadSeparator(&p
))
798 if (!ReadNumber(&p
, &SystemTime
.wMonth
))
800 if (!ReadSeparator(&p
))
802 if (!ReadNumber(&p
, &SystemTime
.wDay
))
807 /* if only entered two digits: */
808 /* assume 2000's if value less than 80 */
809 /* assume 1900's if value greater or equal 80 */
810 if (SystemTime
.wYear
<= 99)
812 if (SystemTime
.wYear
>= 80)
813 SystemTime
.wYear
+= 1900;
815 SystemTime
.wYear
+= 2000;
818 if (!SystemTimeToFileTime(&SystemTime
, &LocalFileTime
))
821 if (!LocalFileTimeToFileTime(&LocalFileTime
, &FileTime
))
824 Time
.u
.LowPart
= FileTime
.dwLowDateTime
;
825 Time
.u
.HighPart
= FileTime
.dwHighDateTime
;
827 if (!RtlTimeToSecondsSince1970(&Time
, pSeconds
))
844 if (!iswdigit(pszString
[0]))
848 while (iswdigit(*pChar
))
850 lHour
= lHour
* 10 + *pChar
- L
'0';
860 if ((*pChar
!= UNICODE_NULL
) &&
864 if ((_wcsicmp(pChar
, AmPmArray
[0]) == 0) ||
865 (_wcsicmp(pChar
, AmPmArray
[1]) == 0))
870 else if ((_wcsicmp(pChar
, AmPmArray
[2]) == 0) ||
871 (_wcsicmp(pChar
, AmPmArray
[3]) == 0))
898 for (i
= 0; i
< 7; i
++)
900 if (_wcsicmp(pszString
, ShortDays
[i
]) == 0 ||
901 _wcsicmp(pszString
, LongDays
[i
]) == 0)
916 PBYTE
*ppLogonBitmap
,
917 PDWORD pdwUnitsPerWeek
)
919 TIME_ZONE_INFORMATION TimeZoneInformation
;
920 PBYTE pLogonBitmap
= NULL
;
921 DWORD dwError
= ERROR_SUCCESS
;
924 WCHAR prevSep
, nextSep
;
925 DWORD dwStartDay
, dwEndDay
, i
, j
;
926 LONG lStartHour
, lEndHour
, lBias
;
929 LPWSTR ShortDays
[7] = {NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
930 LPWSTR LongDays
[7] = {NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
931 LPWSTR AmPmArray
[4] = {NULL
, NULL
, NULL
, NULL
};
933 GetTimeZoneInformation(&TimeZoneInformation
);
934 lBias
= TimeZoneInformation
.Bias
/ 60;
936 pLogonBitmap
= HeapAlloc(GetProcessHeap(),
939 if (pLogonBitmap
== NULL
)
940 return ERROR_OUTOFMEMORY
;
942 if (*pszParams
== UNICODE_NULL
)
947 if (wcsicmp(pszParams
, L
"all") == 0)
949 FillMemory(pLogonBitmap
, UNITS_PER_WEEK
/ 8, 0xFF);
953 for (i
= 0; i
< 7; i
++)
955 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
|
956 FORMAT_MESSAGE_FROM_HMODULE
|
957 FORMAT_MESSAGE_IGNORE_INSERTS
,
961 (LPWSTR
)&ShortDays
[i
],
965 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
|
966 FORMAT_MESSAGE_FROM_HMODULE
|
967 FORMAT_MESSAGE_IGNORE_INSERTS
,
971 (LPWSTR
)&LongDays
[i
],
976 for (i
= 0; i
< 4; i
++)
978 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
|
979 FORMAT_MESSAGE_FROM_HMODULE
|
980 FORMAT_MESSAGE_IGNORE_INSERTS
,
984 (LPWSTR
)&AmPmArray
[i
],
989 ZeroMemory(&DayBitmap
, sizeof(DayBitmap
));
990 ZeroMemory(HourBitmap
, sizeof(HourBitmap
));
992 ZeroMemory(szBuffer
, sizeof(szBuffer
));
995 prevSep
= UNICODE_NULL
;
996 nextSep
= UNICODE_NULL
;
999 if (*ptr1
!= L
'-' && *ptr1
!= L
',' && *ptr1
!= L
';' && *ptr1
!= UNICODE_NULL
)
1009 if (prevSep
!= L
'-')
1011 /* Set first value */
1012 if (iswdigit(szBuffer
[0]))
1015 if (!ParseHour(szBuffer
, AmPmArray
, &lStartHour
))
1021 /* Convert from local timezone to GMT */
1022 lStartHour
+= lBias
;
1024 lStartHour
+= UNITS_PER_WEEK
;
1025 else if (lStartHour
> UNITS_PER_WEEK
)
1026 lStartHour
-= UNITS_PER_WEEK
;
1028 SetBitValue(HourBitmap
, (DWORD
)lStartHour
);
1033 if (!ParseDay(szBuffer
, ShortDays
, LongDays
, &dwStartDay
))
1039 SetBitValue(&DayBitmap
, dwStartDay
);
1044 /* Set second value */
1045 if (iswdigit(szBuffer
[0]))
1048 if (!ParseHour(szBuffer
, AmPmArray
, &lEndHour
))
1054 if (lEndHour
< lStartHour
)
1055 lEndHour
+= HOURS_PER_DAY
;
1056 else if (lEndHour
== lStartHour
)
1057 lEndHour
= lStartHour
+ HOURS_PER_DAY
;
1059 /* Convert from local timezone to GMT */
1062 lEndHour
+= UNITS_PER_WEEK
;
1063 else if (lEndHour
> UNITS_PER_WEEK
)
1064 lEndHour
-= UNITS_PER_WEEK
;
1066 for (i
= (DWORD
)lStartHour
; i
< (DWORD
)lEndHour
; i
++)
1067 SetBitValue(HourBitmap
, i
);
1072 if (!ParseDay(szBuffer
, ShortDays
, LongDays
, &dwEndDay
))
1078 if (dwEndDay
<= dwStartDay
)
1079 dwEndDay
+= DAYS_PER_WEEK
;
1081 for (i
= dwStartDay
; i
<= dwEndDay
; i
++)
1082 SetBitValue(&DayBitmap
, i
% DAYS_PER_WEEK
);
1086 if (*ptr1
== L
';' || *ptr1
== UNICODE_NULL
)
1088 /* Fill the logon hour bitmap */
1089 for (i
= 0; i
< DAYS_PER_WEEK
; i
++)
1091 if (GetBitValue(&DayBitmap
, i
))
1093 for (j
= 0; j
< 48; j
++)
1095 if (GetBitValue(HourBitmap
, j
))
1096 SetBitValue(pLogonBitmap
, ((i
* HOURS_PER_DAY
) + j
) % UNITS_PER_WEEK
);
1101 /* Reset the Bitmaps */
1102 ZeroMemory(&DayBitmap
, sizeof(DayBitmap
));
1103 ZeroMemory(HourBitmap
, sizeof(HourBitmap
));
1106 if (*ptr1
== UNICODE_NULL
)
1109 ZeroMemory(szBuffer
, sizeof(szBuffer
));
1117 for (i
= 0; i
< 7; i
++)
1119 LocalFree(ShortDays
[i
]);
1120 LocalFree(LongDays
[i
]);
1123 for (i
= 0; i
< 4; i
++)
1125 LocalFree(AmPmArray
[i
]);
1128 if (dwError
== ERROR_SUCCESS
)
1130 *ppLogonBitmap
= pLogonBitmap
;
1131 *pdwUnitsPerWeek
= UNITS_PER_WEEK
;
1135 if (pLogonBitmap
!= NULL
)
1136 HeapFree(GetProcessHeap(), 0, pLogonBitmap
);
1137 *ppLogonBitmap
= NULL
;
1138 *pdwUnitsPerWeek
= 0;
1153 BOOL bDelete
= FALSE
;
1155 BOOL bDomain
= FALSE
;
1157 BOOL bRandomPassword
= FALSE
;
1158 LPWSTR lpUserName
= NULL
;
1159 LPWSTR lpPassword
= NULL
;
1160 PUSER_INFO_4 pUserInfo
= NULL
;
1161 USER_INFO_4 UserInfo
;
1162 LPWSTR pWorkstations
= NULL
;
1166 BOOL bPasswordAllocated
= FALSE
;
1167 PBYTE pLogonHours
= NULL
;
1168 DWORD dwUnitsPerWeek
;
1169 NET_API_STATUS Status
;
1172 if ((i
< argc
) && (argv
[i
][0] != L
'/'))
1174 lpUserName
= argv
[i
];
1175 // ConPrintf(StdOut, L"User: %s\n", lpUserName);
1179 if ((i
< argc
) && (argv
[i
][0] != L
'/'))
1181 lpPassword
= argv
[i
];
1182 // ConPrintf(StdOut, L"Password: %s\n", lpPassword);
1186 for (j
= i
; j
< argc
; j
++)
1188 if (_wcsicmp(argv
[j
], L
"/help") == 0)
1190 PrintNetMessage(MSG_USER_HELP
);
1193 else if (_wcsicmp(argv
[j
], L
"/add") == 0)
1197 else if (_wcsicmp(argv
[j
], L
"/delete") == 0)
1201 else if (_wcsicmp(argv
[j
], L
"/domain") == 0)
1203 ConPuts(StdErr
, L
"The /DOMAIN option is not supported yet.\n");
1208 else if (_wcsicmp(argv
[j
], L
"/random") == 0)
1210 bRandomPassword
= TRUE
;
1211 GenerateRandomPassword(&lpPassword
,
1212 &bPasswordAllocated
);
1216 if (lpUserName
== NULL
&& lpPassword
== NULL
)
1218 Status
= EnumerateUsers();
1219 ConPrintf(StdOut
, L
"Status: %lu\n", Status
);
1222 else if (lpUserName
!= NULL
&& lpPassword
== NULL
&& argc
== 3)
1224 Status
= DisplayUser(lpUserName
);
1225 ConPrintf(StdOut
, L
"Status: %lu\n", Status
);
1229 if (bAdd
&& bDelete
)
1235 /* Interactive password input */
1236 if (lpPassword
!= NULL
&& wcscmp(lpPassword
, L
"*") == 0)
1238 ReadPassword(&lpPassword
,
1239 &bPasswordAllocated
);
1242 if (!bAdd
&& !bDelete
)
1244 /* Modify the user */
1245 Status
= NetUserGetInfo(NULL
,
1248 (LPBYTE
*)&pUserInfo
);
1249 if (Status
!= NERR_Success
)
1251 ConPrintf(StdOut
, L
"Status: %lu\n", Status
);
1256 else if (bAdd
&& !bDelete
)
1259 ZeroMemory(&UserInfo
, sizeof(USER_INFO_4
));
1261 UserInfo
.usri4_name
= lpUserName
;
1262 UserInfo
.usri4_password
= lpPassword
;
1263 UserInfo
.usri4_flags
= UF_SCRIPT
| UF_NORMAL_ACCOUNT
;
1264 UserInfo
.usri4_acct_expires
= TIMEQ_FOREVER
;
1265 UserInfo
.usri4_primary_group_id
= DOMAIN_GROUP_RID_USERS
;
1267 pUserInfo
= &UserInfo
;
1270 for (j
= i
; j
< argc
; j
++)
1272 if (_wcsnicmp(argv
[j
], L
"/active:", 8) == 0)
1275 if (_wcsicmp(p
, L
"yes") == 0)
1277 pUserInfo
->usri4_flags
&= ~UF_ACCOUNTDISABLE
;
1279 else if (_wcsicmp(p
, L
"no") == 0)
1281 pUserInfo
->usri4_flags
|= UF_ACCOUNTDISABLE
;
1285 PrintMessageStringV(3952, L
"/ACTIVE");
1290 else if (_wcsnicmp(argv
[j
], L
"/comment:", 9) == 0)
1292 pUserInfo
->usri4_comment
= &argv
[j
][9];
1294 else if (_wcsnicmp(argv
[j
], L
"/countrycode:", 13) == 0)
1297 value
= wcstoul(p
, &endptr
, 10);
1300 PrintMessageStringV(3952, L
"/COUNTRYCODE");
1305 /* Verify the country code */
1306 if (GetCountryFromCountryCode(value
, 0, NULL
))
1307 pUserInfo
->usri4_country_code
= value
;
1309 else if (_wcsnicmp(argv
[j
], L
"/expires:", 9) == 0)
1312 if (_wcsicmp(p
, L
"never") == 0)
1314 pUserInfo
->usri4_acct_expires
= TIMEQ_FOREVER
;
1316 else if (!ParseDate(p
, &pUserInfo
->usri4_acct_expires
))
1318 PrintMessageStringV(3952, L
"/EXPIRES");
1323 else if (_wcsnicmp(argv
[j
], L
"/fullname:", 10) == 0)
1325 pUserInfo
->usri4_full_name
= &argv
[j
][10];
1327 else if (_wcsnicmp(argv
[j
], L
"/homedir:", 9) == 0)
1329 pUserInfo
->usri4_home_dir
= &argv
[j
][9];
1331 else if (_wcsnicmp(argv
[j
], L
"/passwordchg:", 13) == 0)
1334 if (_wcsicmp(p
, L
"yes") == 0)
1336 pUserInfo
->usri4_flags
&= ~UF_PASSWD_CANT_CHANGE
;
1338 else if (_wcsicmp(p
, L
"no") == 0)
1340 pUserInfo
->usri4_flags
|= UF_PASSWD_CANT_CHANGE
;
1344 PrintMessageStringV(3952, L
"/PASSWORDCHG");
1349 else if (_wcsnicmp(argv
[j
], L
"/passwordreq:", 13) == 0)
1352 if (_wcsicmp(p
, L
"yes") == 0)
1354 pUserInfo
->usri4_flags
&= ~UF_PASSWD_NOTREQD
;
1356 else if (_wcsicmp(p
, L
"no") == 0)
1358 pUserInfo
->usri4_flags
|= UF_PASSWD_NOTREQD
;
1362 PrintMessageStringV(3952, L
"/PASSWORDREQ");
1367 else if (_wcsnicmp(argv
[j
], L
"/profilepath:", 13) == 0)
1369 pUserInfo
->usri4_profile
= &argv
[j
][13];
1371 else if (_wcsnicmp(argv
[j
], L
"/scriptpath:", 12) == 0)
1373 pUserInfo
->usri4_script_path
= &argv
[j
][12];
1375 else if (_wcsnicmp(argv
[j
], L
"/times:", 7) == 0)
1377 Status
= ParseLogonHours(&argv
[j
][7],
1380 if (Status
== ERROR_SUCCESS
)
1382 pUserInfo
->usri4_logon_hours
= pLogonHours
;
1383 pUserInfo
->usri4_units_per_week
= dwUnitsPerWeek
;
1387 PrintMessageString(Status
);
1391 else if (_wcsnicmp(argv
[j
], L
"/usercomment:", 13) == 0)
1393 pUserInfo
->usri4_usr_comment
= &argv
[j
][13];
1395 else if (_wcsnicmp(argv
[j
], L
"/workstations:", 14) == 0)
1398 if (wcscmp(p
, L
"*") == 0 || wcscmp(p
, L
"") == 0)
1400 pUserInfo
->usri4_workstations
= NULL
;
1404 Status
= BuildWorkstationsList(&pWorkstations
, p
);
1405 if (Status
== NERR_Success
)
1407 pUserInfo
->usri4_workstations
= pWorkstations
;
1411 ConPrintf(StdOut
, L
"Status %lu\n\n", Status
);
1419 if (!bAdd
&& !bDelete
)
1421 /* Modify the user */
1422 Status
= NetUserSetInfo(NULL
,
1427 ConPrintf(StdOut
, L
"Status: %lu\n", Status
);
1429 else if (bAdd
&& !bDelete
)
1432 Status
= NetUserAdd(NULL
,
1436 ConPrintf(StdOut
, L
"Status: %lu\n", Status
);
1438 else if (!bAdd
&& bDelete
)
1440 /* Delete the user */
1441 Status
= NetUserDel(NULL
,
1443 ConPrintf(StdOut
, L
"Status: %lu\n", Status
);
1446 if (Status
== NERR_Success
&&
1447 lpPassword
!= NULL
&&
1448 bRandomPassword
== TRUE
)
1450 PrintMessageStringV(3968, lpUserName
, lpPassword
);
1454 if (pLogonHours
!= NULL
)
1455 HeapFree(GetProcessHeap(), 0, pLogonHours
);
1457 if (pWorkstations
!= NULL
)
1458 HeapFree(GetProcessHeap(), 0, pWorkstations
);
1460 if ((bPasswordAllocated
== TRUE
) && (lpPassword
!= NULL
))
1461 HeapFree(GetProcessHeap(), 0, lpPassword
);
1463 if (!bAdd
&& !bDelete
&& pUserInfo
!= NULL
)
1464 NetApiBufferFree(pUserInfo
);
1468 PrintMessageString(4381);
1469 ConPuts(StdOut
, L
"\n");
1470 PrintNetMessage(MSG_USER_SYNTAX
);