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)
16 typedef struct _COUNTY_TABLE
20 } COUNTRY_TABLE
, *PCOUNTRY_TABLE
;
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
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
43 { 86, 5098}, // China (PRC)
44 { 88, 5099}, // Taiwan
46 {351, 5101}, // Portugal
47 {358, 5102}, // Finland
48 {785, 5103}, // Arabic
49 {972, 5104} }; // Hebrew
54 CompareInfo(const void *a
, const void *b
)
56 return _wcsicmp(((PUSER_INFO_0
)a
)->usri0_name
,
57 ((PUSER_INFO_0
)b
)->usri0_name
);
65 PUSER_INFO_0 pBuffer
= NULL
;
66 PSERVER_INFO_100 pServer
= NULL
;
67 DWORD dwRead
= 0, dwTotal
= 0;
69 DWORD ResumeHandle
= 0;
70 NET_API_STATUS Status
;
72 Status
= NetServerGetInfo(NULL
,
75 if (Status
!= NERR_Success
)
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");
84 NetApiBufferFree(pServer
);
88 Status
= NetUserEnum(NULL
,
96 if ((Status
!= NERR_Success
) && (Status
!= ERROR_MORE_DATA
))
101 sizeof(PUSER_INFO_0
),
104 for (i
= 0; i
< dwRead
; i
++)
106 if (pBuffer
[i
].usri0_name
)
107 ConPrintf(StdOut
, L
"%s\n", pBuffer
[i
].usri0_name
);
110 NetApiBufferFree(pBuffer
);
113 while (Status
== ERROR_MORE_DATA
);
121 PrintDateTime(DWORD dwSeconds
)
125 SYSTEMTIME SystemTime
;
126 WCHAR DateBuffer
[80];
127 WCHAR TimeBuffer
[80];
129 RtlSecondsSince1970ToTime(dwSeconds
, &Time
);
130 FileTime
.dwLowDateTime
= Time
.u
.LowPart
;
131 FileTime
.dwHighDateTime
= Time
.u
.HighPart
;
132 FileTimeToLocalFileTime(&FileTime
, &FileTime
);
133 FileTimeToSystemTime(&FileTime
, &SystemTime
);
135 GetDateFormatW(LOCALE_USER_DEFAULT
,
140 ARRAYSIZE(DateBuffer
));
142 GetTimeFormatW(LOCALE_USER_DEFAULT
,
147 ARRAYSIZE(TimeBuffer
));
149 ConPrintf(StdOut
, L
"%s %s", DateBuffer
, TimeBuffer
);
155 PrintLocalTime(DWORD dwSeconds
)
159 SYSTEMTIME SystemTime
;
160 WCHAR TimeBuffer
[80];
162 RtlSecondsSince1970ToTime(dwSeconds
, &Time
);
163 FileTime
.dwLowDateTime
= Time
.u
.LowPart
;
164 FileTime
.dwHighDateTime
= Time
.u
.HighPart
;
165 FileTimeToSystemTime(&FileTime
, &SystemTime
);
167 GetTimeFormatW(LOCALE_USER_DEFAULT
,
172 ARRAYSIZE(TimeBuffer
));
174 ConPrintf(StdOut
, L
"%s", TimeBuffer
);
180 GetTimeInSeconds(VOID
)
186 GetSystemTimeAsFileTime(&FileTime
);
187 Time
.u
.LowPart
= FileTime
.dwLowDateTime
;
188 Time
.u
.HighPart
= FileTime
.dwHighDateTime
;
189 RtlTimeToSecondsSince1970(&Time
, &dwSeconds
);
197 GetCountryFromCountryCode(
198 _In_ DWORD dwCountryCode
,
199 _In_ DWORD dwCountryLength
,
200 _Out_ PWSTR szCountryBuffer
)
204 for (i
= 0; i
< ARRAYSIZE(CountryTable
); i
++)
206 if (CountryTable
[i
].dwCountryCode
== dwCountryCode
)
208 if (szCountryBuffer
!= NULL
&& dwCountryLength
> 0)
210 FormatMessageW(FORMAT_MESSAGE_FROM_HMODULE
| FORMAT_MESSAGE_IGNORE_INSERTS
,
212 CountryTable
[i
].dwMessageId
,
233 DWORD dwIndex
= dwBitNumber
/ 8;
234 BYTE Mask
= 1 << (dwBitNumber
& 7);
236 return ((pLogonHours
[dwIndex
] & Mask
) != 0);
243 DWORD dwUnitsPerWeek
,
247 DWORD dwUnitsPerDay
, dwBitNumber
, dwSecondsPerUnit
;
248 DWORD dwStartTime
, dwEndTime
, dwStartDay
, dwEndDay
;
249 BOOL bBitValue
, bFirst
= TRUE
;
251 if ((dwUnitsPerWeek
== 0) ||
252 ((dwUnitsPerWeek
%7) != 0))
255 dwUnitsPerDay
= dwUnitsPerWeek
/ 7;
257 if (((dwUnitsPerDay
% 24) != 0) ||
258 ((dwUnitsPerDay
/ 24) > 6))
261 dwSecondsPerUnit
= (SECONDS_PER_DAY
) / dwUnitsPerDay
;
263 for (dwBitNumber
= 0; dwBitNumber
< dwUnitsPerWeek
; dwBitNumber
++)
265 bBitValue
= BitValue(pLogonHours
, dwBitNumber
);
268 dwStartTime
= dwSecondsPerUnit
* dwBitNumber
;
270 while (bBitValue
!= 0 && dwBitNumber
< dwUnitsPerWeek
)
273 if (dwBitNumber
< dwUnitsPerWeek
)
274 bBitValue
= BitValue(pLogonHours
, dwBitNumber
);
277 dwEndTime
= dwSecondsPerUnit
* dwBitNumber
;
280 PrintPadding(L
' ', nPaddedLength
);
282 if (dwStartTime
== 0 && dwEndTime
== (SECONDS_PER_DAY
* 7))
284 PrintMessageString(4302);
285 ConPuts(StdOut
, L
"\n");
289 dwStartDay
= dwStartTime
/ SECONDS_PER_DAY
;
290 dwEndDay
= (dwEndTime
/ SECONDS_PER_DAY
) % 7;
292 PrintMessageString(4307 + dwStartDay
);
293 ConPuts(StdOut
, L
" ");
294 PrintLocalTime((dwStartTime
% SECONDS_PER_DAY
) + SECONDS_PER_HOUR
);
296 ConPrintf(StdOut
, L
" - ");
297 if (dwStartDay
!= dwEndDay
)
299 PrintMessageString(4307 + dwEndDay
);
300 ConPuts(StdOut
, L
" ");
303 PrintLocalTime((dwEndTime
% SECONDS_PER_DAY
) + SECONDS_PER_HOUR
);
304 ConPuts(StdOut
, L
"\n");
314 PrintMessageString(4434);
315 ConPuts(StdOut
, L
"\n");
322 DisplayUser(LPWSTR lpUserName
)
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
;
333 INT nPaddedLength
= 36;
334 NET_API_STATUS Status
;
336 /* Modify the user */
337 Status
= NetUserGetInfo(NULL
,
340 (LPBYTE
*)&pUserInfo
);
341 if (Status
!= NERR_Success
)
344 Status
= NetUserModalsGet(NULL
,
346 (LPBYTE
*)&pUserModals
);
347 if (Status
!= NERR_Success
)
350 Status
= NetUserGetLocalGroups(NULL
,
354 (LPBYTE
*)&pLocalGroupInfo
,
355 MAX_PREFERRED_LENGTH
,
358 if (Status
!= NERR_Success
)
361 Status
= NetUserGetGroups(NULL
,
364 (LPBYTE
*)&pGroupInfo
,
365 MAX_PREFERRED_LENGTH
,
368 if (Status
!= NERR_Success
)
371 PrintPaddedMessageString(4411, nPaddedLength
);
372 ConPrintf(StdOut
, L
"%s\n", pUserInfo
->usri4_name
);
374 PrintPaddedMessageString(4412, nPaddedLength
);
375 ConPrintf(StdOut
, L
"%s\n", pUserInfo
->usri4_full_name
);
377 PrintPaddedMessageString(4413, nPaddedLength
);
378 ConPrintf(StdOut
, L
"%s\n", pUserInfo
->usri4_comment
);
380 PrintPaddedMessageString(4414, nPaddedLength
);
381 ConPrintf(StdOut
, L
"%s\n", pUserInfo
->usri4_usr_comment
);
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
);
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);
394 PrintMessageString(4300);
395 ConPuts(StdOut
, L
"\n");
397 PrintPaddedMessageString(4420, nPaddedLength
);
398 if (pUserInfo
->usri4_acct_expires
== TIMEQ_FOREVER
)
399 PrintMessageString(4305);
401 PrintDateTime(pUserInfo
->usri4_acct_expires
);
402 ConPuts(StdOut
, L
"\n\n");
404 PrintPaddedMessageString(4421, nPaddedLength
);
405 dwLastSet
= GetTimeInSeconds() - pUserInfo
->usri4_password_age
;
406 PrintDateTime(dwLastSet
);
407 ConPuts(StdOut
, L
"\n");
409 PrintPaddedMessageString(4422, nPaddedLength
);
410 if ((pUserInfo
->usri4_flags
& UF_DONT_EXPIRE_PASSWD
) || pUserModals
->usrmod0_max_passwd_age
== TIMEQ_FOREVER
)
411 PrintMessageString(4305);
413 PrintDateTime(dwLastSet
+ pUserModals
->usrmod0_max_passwd_age
);
414 ConPuts(StdOut
, L
"\n");
416 PrintPaddedMessageString(4423, nPaddedLength
);
417 PrintDateTime(dwLastSet
+ pUserModals
->usrmod0_min_passwd_age
);
418 ConPuts(StdOut
, L
"\n");
420 PrintPaddedMessageString(4437, nPaddedLength
);
421 PrintMessageString((pUserInfo
->usri4_flags
& UF_PASSWD_NOTREQD
) ? 4301 : 4300);
422 ConPuts(StdOut
, L
"\n");
424 PrintPaddedMessageString(4438, nPaddedLength
);
425 PrintMessageString((pUserInfo
->usri4_flags
& UF_PASSWD_CANT_CHANGE
) ? 4301 : 4300);
426 ConPuts(StdOut
, L
"\n\n");
428 PrintPaddedMessageString(4424, nPaddedLength
);
429 if (pUserInfo
->usri4_workstations
== NULL
|| wcslen(pUserInfo
->usri4_workstations
) == 0)
430 PrintMessageString(4302);
432 ConPrintf(StdOut
, L
"%s", pUserInfo
->usri4_workstations
);
433 ConPuts(StdOut
, L
"\n");
435 PrintPaddedMessageString(4429, nPaddedLength
);
436 ConPrintf(StdOut
, L
"%s\n", pUserInfo
->usri4_script_path
);
438 PrintPaddedMessageString(4439, nPaddedLength
);
439 ConPrintf(StdOut
, L
"%s\n", pUserInfo
->usri4_profile
);
441 PrintPaddedMessageString(4436, nPaddedLength
);
442 ConPrintf(StdOut
, L
"%s\n", pUserInfo
->usri4_home_dir
);
444 PrintPaddedMessageString(4430, nPaddedLength
);
445 if (pUserInfo
->usri4_last_logon
== 0)
446 PrintMessageString(4305);
448 PrintDateTime(pUserInfo
->usri4_last_logon
);
449 ConPuts(StdOut
, L
"\n\n");
451 PrintPaddedMessageString(4432, nPaddedLength
);
452 if (pUserInfo
->usri4_logon_hours
== NULL
)
454 PrintMessageString(4302);
455 ConPuts(StdOut
, L
"\n");
459 PrintLogonHours(pUserInfo
->usri4_units_per_week
,
460 pUserInfo
->usri4_logon_hours
,
464 ConPuts(StdOut
, L
"\n");
465 PrintPaddedMessageString(4427, nPaddedLength
);
466 if (dwLocalGroupTotal
!= 0 && pLocalGroupInfo
!= NULL
)
468 for (i
= 0; i
< dwLocalGroupTotal
; i
++)
471 PrintPadding(L
' ', nPaddedLength
);
472 ConPrintf(StdOut
, L
"*%s\n", pLocalGroupInfo
[i
].lgrui0_name
);
477 ConPuts(StdOut
, L
"\n");
480 PrintPaddedMessageString(4431, nPaddedLength
);
481 if (dwGroupTotal
!= 0 && pGroupInfo
!= NULL
)
483 for (i
= 0; i
< dwGroupTotal
; i
++)
486 PrintPadding(L
' ', nPaddedLength
);
487 ConPrintf(StdOut
, L
"*%s\n", pGroupInfo
[i
].grui0_name
);
492 ConPuts(StdOut
, L
"\n");
496 if (pGroupInfo
!= NULL
)
497 NetApiBufferFree(pGroupInfo
);
499 if (pLocalGroupInfo
!= NULL
)
500 NetApiBufferFree(pLocalGroupInfo
);
502 if (pUserModals
!= NULL
)
503 NetApiBufferFree(pUserModals
);
505 if (pUserInfo
!= NULL
)
506 NetApiBufferFree(pUserInfo
);
518 WCHAR szPassword1
[PWLEN
+ 1];
519 WCHAR szPassword2
[PWLEN
+ 1];
522 *lpAllocated
= FALSE
;
526 PrintMessageString(4358);
527 ReadFromConsole(szPassword1
, PWLEN
+ 1, FALSE
);
528 ConPuts(StdOut
, L
"\n");
530 PrintMessageString(4361);
531 ReadFromConsole(szPassword2
, PWLEN
+ 1, FALSE
);
532 ConPuts(StdOut
, L
"\n");
534 if (wcslen(szPassword1
) == wcslen(szPassword2
) &&
535 wcscmp(szPassword1
, szPassword2
) == 0)
537 ptr
= HeapAlloc(GetProcessHeap(),
539 (wcslen(szPassword1
) + 1) * sizeof(WCHAR
));
542 wcscpy(ptr
, szPassword1
);
550 ConPuts(StdOut
, L
"\n");
551 PrintMessageString(3728);
560 GenerateRandomPassword(
564 LPWSTR pPassword
= NULL
;
565 INT nCharsLen
, i
, nLength
= 8;
567 srand(GetTickCount());
569 pPassword
= HeapAlloc(GetProcessHeap(),
571 (nLength
+ 1) * sizeof(WCHAR
));
572 if (pPassword
== NULL
)
575 nCharsLen
= wcslen(szPasswordChars
);
577 for (i
= 0; i
< nLength
; i
++)
579 pPassword
[i
] = szPasswordChars
[rand() % nCharsLen
];
582 *lpPassword
= pPassword
;
589 BuildWorkstationsList(
590 _Out_ PWSTR
*pWorkstationsList
,
593 BOOL isLastSep
, isSep
;
601 /* Check for invalid characters in the raw string */
602 if (wcspbrk(pRaw
, L
"/[]=?\\+:.") != NULL
)
605 /* Count the number of workstations in the list and
606 * the required buffer size */
609 nRawLength
= wcslen(pRaw
);
610 for (i
= 0; i
< nRawLength
; i
++)
613 if (c
== L
',' || c
== L
';')
618 if ((isLastSep
== FALSE
) && (i
!= 0) && (i
!= nRawLength
- 1))
625 if (isLastSep
== TRUE
|| (isLastSep
== FALSE
&& i
== 0))
635 /* Leave, if there are no workstations in the list */
638 pWorkstationsList
= NULL
;
642 /* Fail if there are more than eight workstations in the list */
646 /* Allocate the buffer for the clean workstation list */
647 pList
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, nLength
* sizeof(WCHAR
));
649 return ERROR_NOT_ENOUGH_MEMORY
;
651 /* Build the clean workstation list */
654 nRawLength
= wcslen(pRaw
);
655 for (i
= 0, j
= 0; i
< nRawLength
; i
++)
658 if (c
== L
',' || c
== L
';')
663 if ((isLastSep
== FALSE
) && (i
!= 0) && (i
!= nRawLength
- 1))
674 if (isLastSep
== TRUE
|| (isLastSep
== FALSE
&& i
== 0))
682 *pWorkstationsList
= pList
;
697 while (iswdigit(**s
))
699 *pwValue
= *pwValue
* 10 + **s
- L
'0';
712 if (**s
== L
'/' || **s
== L
'.')
728 SYSTEMTIME SystemTime
= {0};
729 FILETIME LocalFileTime
, FileTime
;
737 GetLocaleInfoW(LOCALE_USER_DEFAULT
,
746 if (!ReadNumber(&p
, &SystemTime
.wMonth
))
748 if (!ReadSeparator(&p
))
750 if (!ReadNumber(&p
, &SystemTime
.wDay
))
752 if (!ReadSeparator(&p
))
754 if (!ReadNumber(&p
, &SystemTime
.wYear
))
759 if (!ReadNumber(&p
, &SystemTime
.wDay
))
761 if (!ReadSeparator(&p
))
763 if (!ReadNumber(&p
, &SystemTime
.wMonth
))
765 if (!ReadSeparator(&p
))
767 if (!ReadNumber(&p
, &SystemTime
.wYear
))
772 if (!ReadNumber(&p
, &SystemTime
.wYear
))
774 if (!ReadSeparator(&p
))
776 if (!ReadNumber(&p
, &SystemTime
.wMonth
))
778 if (!ReadSeparator(&p
))
780 if (!ReadNumber(&p
, &SystemTime
.wDay
))
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)
790 if (SystemTime
.wYear
>= 80)
791 SystemTime
.wYear
+= 1900;
793 SystemTime
.wYear
+= 2000;
796 if (!SystemTimeToFileTime(&SystemTime
, &LocalFileTime
))
799 if (!LocalFileTimeToFileTime(&LocalFileTime
, &FileTime
))
802 Time
.u
.LowPart
= FileTime
.dwLowDateTime
;
803 Time
.u
.HighPart
= FileTime
.dwHighDateTime
;
805 if (!RtlTimeToSecondsSince1970(&Time
, pSeconds
))
817 PDWORD pdwUnitsPerWeek
)
819 PBYTE pLogonHours
= NULL
;
820 DWORD dwError
= ERROR_SUCCESS
;
822 pLogonHours
= HeapAlloc(GetProcessHeap(),
825 if (pLogonHours
== NULL
)
826 return ERROR_OUTOFMEMORY
;
828 if (*pszParams
== UNICODE_NULL
)
833 if (wcsicmp(pszParams
, L
"all") == 0)
835 FillMemory(pLogonHours
, UNITS_PER_WEEK
/ 8, 0xFF);
840 /* Mockup error because we do not parse the line yet */
844 if (dwError
== ERROR_SUCCESS
)
846 *ppLogonHours
= pLogonHours
;
847 *pdwUnitsPerWeek
= UNITS_PER_WEEK
;
851 if (pLogonHours
!= NULL
)
852 HeapFree(GetProcessHeap(), 0, pLogonHours
);
867 BOOL bDelete
= FALSE
;
869 BOOL bDomain
= FALSE
;
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
;
880 BOOL bPasswordAllocated
= FALSE
;
881 PBYTE pLogonHours
= NULL
;
882 DWORD dwUnitsPerWeek
;
883 NET_API_STATUS Status
;
886 if ((i
< argc
) && (argv
[i
][0] != L
'/'))
888 lpUserName
= argv
[i
];
889 // ConPrintf(StdOut, L"User: %s\n", lpUserName);
893 if ((i
< argc
) && (argv
[i
][0] != L
'/'))
895 lpPassword
= argv
[i
];
896 // ConPrintf(StdOut, L"Password: %s\n", lpPassword);
900 for (j
= i
; j
< argc
; j
++)
902 if (_wcsicmp(argv
[j
], L
"/help") == 0)
904 PrintNetMessage(MSG_USER_HELP
);
907 else if (_wcsicmp(argv
[j
], L
"/add") == 0)
911 else if (_wcsicmp(argv
[j
], L
"/delete") == 0)
915 else if (_wcsicmp(argv
[j
], L
"/domain") == 0)
917 ConPuts(StdErr
, L
"The /DOMAIN option is not supported yet.\n");
922 else if (_wcsicmp(argv
[j
], L
"/random") == 0)
924 bRandomPassword
= TRUE
;
925 GenerateRandomPassword(&lpPassword
,
926 &bPasswordAllocated
);
930 if (lpUserName
== NULL
&& lpPassword
== NULL
)
932 Status
= EnumerateUsers();
933 ConPrintf(StdOut
, L
"Status: %lu\n", Status
);
936 else if (lpUserName
!= NULL
&& lpPassword
== NULL
&& argc
== 3)
938 Status
= DisplayUser(lpUserName
);
939 ConPrintf(StdOut
, L
"Status: %lu\n", Status
);
949 /* Interactive password input */
950 if (lpPassword
!= NULL
&& wcscmp(lpPassword
, L
"*") == 0)
952 ReadPassword(&lpPassword
,
953 &bPasswordAllocated
);
956 if (!bAdd
&& !bDelete
)
958 /* Modify the user */
959 Status
= NetUserGetInfo(NULL
,
962 (LPBYTE
*)&pUserInfo
);
963 if (Status
!= NERR_Success
)
965 ConPrintf(StdOut
, L
"Status: %lu\n", Status
);
970 else if (bAdd
&& !bDelete
)
973 ZeroMemory(&UserInfo
, sizeof(USER_INFO_4
));
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
;
981 pUserInfo
= &UserInfo
;
984 for (j
= i
; j
< argc
; j
++)
986 if (_wcsnicmp(argv
[j
], L
"/active:", 8) == 0)
989 if (_wcsicmp(p
, L
"yes") == 0)
991 pUserInfo
->usri4_flags
&= ~UF_ACCOUNTDISABLE
;
993 else if (_wcsicmp(p
, L
"no") == 0)
995 pUserInfo
->usri4_flags
|= UF_ACCOUNTDISABLE
;
999 PrintMessageStringV(3952, L
"/ACTIVE");
1004 else if (_wcsnicmp(argv
[j
], L
"/comment:", 9) == 0)
1006 pUserInfo
->usri4_comment
= &argv
[j
][9];
1008 else if (_wcsnicmp(argv
[j
], L
"/countrycode:", 13) == 0)
1011 value
= wcstoul(p
, &endptr
, 10);
1014 PrintMessageStringV(3952, L
"/COUNTRYCODE");
1019 /* Verify the country code */
1020 if (GetCountryFromCountryCode(value
, 0, NULL
))
1021 pUserInfo
->usri4_country_code
= value
;
1023 else if (_wcsnicmp(argv
[j
], L
"/expires:", 9) == 0)
1026 if (_wcsicmp(p
, L
"never") == 0)
1028 pUserInfo
->usri4_acct_expires
= TIMEQ_FOREVER
;
1030 else if (!ParseDate(p
, &pUserInfo
->usri4_acct_expires
))
1032 PrintMessageStringV(3952, L
"/EXPIRES");
1037 else if (_wcsnicmp(argv
[j
], L
"/fullname:", 10) == 0)
1039 pUserInfo
->usri4_full_name
= &argv
[j
][10];
1041 else if (_wcsnicmp(argv
[j
], L
"/homedir:", 9) == 0)
1043 pUserInfo
->usri4_home_dir
= &argv
[j
][9];
1045 else if (_wcsnicmp(argv
[j
], L
"/passwordchg:", 13) == 0)
1048 if (_wcsicmp(p
, L
"yes") == 0)
1050 pUserInfo
->usri4_flags
&= ~UF_PASSWD_CANT_CHANGE
;
1052 else if (_wcsicmp(p
, L
"no") == 0)
1054 pUserInfo
->usri4_flags
|= UF_PASSWD_CANT_CHANGE
;
1058 PrintMessageStringV(3952, L
"/PASSWORDCHG");
1063 else if (_wcsnicmp(argv
[j
], L
"/passwordreq:", 13) == 0)
1066 if (_wcsicmp(p
, L
"yes") == 0)
1068 pUserInfo
->usri4_flags
&= ~UF_PASSWD_NOTREQD
;
1070 else if (_wcsicmp(p
, L
"no") == 0)
1072 pUserInfo
->usri4_flags
|= UF_PASSWD_NOTREQD
;
1076 PrintMessageStringV(3952, L
"/PASSWORDREQ");
1081 else if (_wcsnicmp(argv
[j
], L
"/profilepath:", 13) == 0)
1083 pUserInfo
->usri4_profile
= &argv
[j
][13];
1085 else if (_wcsnicmp(argv
[j
], L
"/scriptpath:", 12) == 0)
1087 pUserInfo
->usri4_script_path
= &argv
[j
][12];
1089 else if (_wcsnicmp(argv
[j
], L
"/times:", 7) == 0)
1091 Status
= ParseLogonHours(&argv
[j
][7],
1094 if (Status
== ERROR_SUCCESS
)
1096 pUserInfo
->usri4_logon_hours
= pLogonHours
;
1097 pUserInfo
->usri4_units_per_week
= dwUnitsPerWeek
;
1101 PrintMessageString(Status
);
1105 else if (_wcsnicmp(argv
[j
], L
"/usercomment:", 13) == 0)
1107 pUserInfo
->usri4_usr_comment
= &argv
[j
][13];
1109 else if (_wcsnicmp(argv
[j
], L
"/workstations:", 14) == 0)
1112 if (wcscmp(p
, L
"*") == 0 || wcscmp(p
, L
"") == 0)
1114 pUserInfo
->usri4_workstations
= NULL
;
1118 Status
= BuildWorkstationsList(&pWorkstations
, p
);
1119 if (Status
== NERR_Success
)
1121 pUserInfo
->usri4_workstations
= pWorkstations
;
1125 ConPrintf(StdOut
, L
"Status %lu\n\n", Status
);
1133 if (!bAdd
&& !bDelete
)
1135 /* Modify the user */
1136 Status
= NetUserSetInfo(NULL
,
1141 ConPrintf(StdOut
, L
"Status: %lu\n", Status
);
1143 else if (bAdd
&& !bDelete
)
1146 Status
= NetUserAdd(NULL
,
1150 ConPrintf(StdOut
, L
"Status: %lu\n", Status
);
1152 else if (!bAdd
&& bDelete
)
1154 /* Delete the user */
1155 Status
= NetUserDel(NULL
,
1157 ConPrintf(StdOut
, L
"Status: %lu\n", Status
);
1160 if (Status
== NERR_Success
&&
1161 lpPassword
!= NULL
&&
1162 bRandomPassword
== TRUE
)
1164 PrintMessageStringV(3968, lpUserName
, lpPassword
);
1168 if (pLogonHours
!= NULL
)
1169 HeapFree(GetProcessHeap(), 0, pLogonHours
);
1171 if (pWorkstations
!= NULL
)
1172 HeapFree(GetProcessHeap(), 0, pWorkstations
);
1174 if ((bPasswordAllocated
== TRUE
) && (lpPassword
!= NULL
))
1175 HeapFree(GetProcessHeap(), 0, lpPassword
);
1177 if (!bAdd
&& !bDelete
&& pUserInfo
!= NULL
)
1178 NetApiBufferFree(pUserInfo
);
1182 PrintMessageString(4381);
1183 ConPuts(StdOut
, L
"\n");
1184 PrintNetMessage(MSG_USER_SYNTAX
);