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
16 CompareInfo(const void *a
,
19 return _wcsicmp(((PUSER_INFO_0
)a
)->usri0_name
,
20 ((PUSER_INFO_0
)b
)->usri0_name
);
28 PUSER_INFO_0 pBuffer
= NULL
;
29 PSERVER_INFO_100 pServer
= NULL
;
30 DWORD dwRead
= 0, dwTotal
= 0;
32 DWORD_PTR ResumeHandle
= 0;
33 NET_API_STATUS Status
;
35 Status
= NetServerGetInfo(NULL
,
38 if (Status
!= NERR_Success
)
41 PrintToConsole(L
"\n");
42 PrintResourceString(IDS_USER_ACCOUNTS
, pServer
->sv100_name
);
43 PrintToConsole(L
"\n\n");
44 PrintPadding(L
'-', 79);
45 PrintToConsole(L
"\n");
47 NetApiBufferFree(pServer
);
51 Status
= NetUserEnum(NULL
,
59 if ((Status
!= NERR_Success
) && (Status
!= ERROR_MORE_DATA
))
67 for (i
= 0; i
< dwRead
; i
++)
69 if (pBuffer
[i
].usri0_name
)
70 PrintToConsole(L
"%s\n", pBuffer
[i
].usri0_name
);
75 NetApiBufferFree(pBuffer
);
79 while (Status
== ERROR_MORE_DATA
);
87 PrintDateTime(DWORD dwSeconds
)
91 SYSTEMTIME SystemTime
;
95 RtlSecondsSince1970ToTime(dwSeconds
, &Time
);
96 FileTime
.dwLowDateTime
= Time
.u
.LowPart
;
97 FileTime
.dwHighDateTime
= Time
.u
.HighPart
;
98 FileTimeToLocalFileTime(&FileTime
, &FileTime
);
99 FileTimeToSystemTime(&FileTime
, &SystemTime
);
101 GetDateFormatW(LOCALE_USER_DEFAULT
,
108 GetTimeFormatW(LOCALE_USER_DEFAULT
,
115 PrintToConsole(L
"%s %s", DateBuffer
, TimeBuffer
);
121 GetTimeInSeconds(VOID
)
127 GetSystemTimeAsFileTime(&FileTime
);
128 Time
.u
.LowPart
= FileTime
.dwLowDateTime
;
129 Time
.u
.HighPart
= FileTime
.dwHighDateTime
;
130 RtlTimeToSecondsSince1970(&Time
, &dwSeconds
);
138 DisplayUser(LPWSTR lpUserName
)
140 PUSER_MODALS_INFO_0 pUserModals
= NULL
;
141 PUSER_INFO_4 pUserInfo
= NULL
;
142 PLOCALGROUP_USERS_INFO_0 pLocalGroupInfo
= NULL
;
143 PGROUP_USERS_INFO_0 pGroupInfo
= NULL
;
144 DWORD dwLocalGroupRead
, dwLocalGroupTotal
;
145 DWORD dwGroupRead
, dwGroupTotal
;
148 INT nPaddedLength
= 29;
149 NET_API_STATUS Status
;
151 /* Modify the user */
152 Status
= NetUserGetInfo(NULL
,
155 (LPBYTE
*)&pUserInfo
);
156 if (Status
!= NERR_Success
)
159 Status
= NetUserModalsGet(NULL
,
161 (LPBYTE
*)&pUserModals
);
162 if (Status
!= NERR_Success
)
165 Status
= NetUserGetLocalGroups(NULL
,
169 (LPBYTE
*)&pLocalGroupInfo
,
170 MAX_PREFERRED_LENGTH
,
173 if (Status
!= NERR_Success
)
176 Status
= NetUserGetGroups(NULL
,
179 (LPBYTE
*)&pGroupInfo
,
180 MAX_PREFERRED_LENGTH
,
183 if (Status
!= NERR_Success
)
186 PrintPaddedResourceString(IDS_USER_NAME
, nPaddedLength
);
187 PrintToConsole(L
"%s\n", pUserInfo
->usri4_name
);
189 PrintPaddedResourceString(IDS_USER_FULL_NAME
, nPaddedLength
);
190 PrintToConsole(L
"%s\n", pUserInfo
->usri4_full_name
);
192 PrintPaddedResourceString(IDS_USER_COMMENT
, nPaddedLength
);
193 PrintToConsole(L
"%s\n", pUserInfo
->usri4_comment
);
195 PrintPaddedResourceString(IDS_USER_USER_COMMENT
, nPaddedLength
);
196 PrintToConsole(L
"%s\n", pUserInfo
->usri4_usr_comment
);
198 PrintPaddedResourceString(IDS_USER_COUNTRY_CODE
, nPaddedLength
);
199 PrintToConsole(L
"%03ld ()\n", pUserInfo
->usri4_country_code
);
201 PrintPaddedResourceString(IDS_USER_ACCOUNT_ACTIVE
, nPaddedLength
);
202 if (pUserInfo
->usri4_flags
& UF_ACCOUNTDISABLE
)
203 PrintResourceString(IDS_GENERIC_NO
);
204 else if (pUserInfo
->usri4_flags
& UF_LOCKOUT
)
205 PrintResourceString(IDS_GENERIC_LOCKED
);
207 PrintResourceString(IDS_GENERIC_YES
);
208 PrintToConsole(L
"\n");
210 PrintPaddedResourceString(IDS_USER_ACCOUNT_EXPIRES
, nPaddedLength
);
211 if (pUserInfo
->usri4_acct_expires
== TIMEQ_FOREVER
)
212 PrintResourceString(IDS_GENERIC_NEVER
);
214 PrintDateTime(pUserInfo
->usri4_acct_expires
);
215 PrintToConsole(L
"\n\n");
217 PrintPaddedResourceString(IDS_USER_PW_LAST_SET
, nPaddedLength
);
218 dwLastSet
= GetTimeInSeconds() - pUserInfo
->usri4_password_age
;
219 PrintDateTime(dwLastSet
);
221 PrintPaddedResourceString(IDS_USER_PW_EXPIRES
, nPaddedLength
);
222 if ((pUserInfo
->usri4_flags
& UF_DONT_EXPIRE_PASSWD
) || pUserModals
->usrmod0_max_passwd_age
== TIMEQ_FOREVER
)
223 PrintResourceString(IDS_GENERIC_NEVER
);
225 PrintDateTime(dwLastSet
+ pUserModals
->usrmod0_max_passwd_age
);
226 PrintToConsole(L
"\n");
228 PrintPaddedResourceString(IDS_USER_PW_CHANGEABLE
, nPaddedLength
);
229 PrintDateTime(dwLastSet
+ pUserModals
->usrmod0_min_passwd_age
);
231 PrintPaddedResourceString(IDS_USER_PW_REQUIRED
, nPaddedLength
);
232 PrintResourceString((pUserInfo
->usri4_flags
& UF_PASSWD_NOTREQD
) ? IDS_GENERIC_NO
: IDS_GENERIC_YES
);
233 PrintToConsole(L
"\n");
235 PrintPaddedResourceString(IDS_USER_CHANGE_PW
, nPaddedLength
);
236 PrintResourceString((pUserInfo
->usri4_flags
& UF_PASSWD_CANT_CHANGE
) ? IDS_GENERIC_NO
: IDS_GENERIC_YES
);
237 PrintToConsole(L
"\n\n");
239 PrintPaddedResourceString(IDS_USER_WORKSTATIONS
, nPaddedLength
);
240 if (pUserInfo
->usri4_workstations
== NULL
|| wcslen(pUserInfo
->usri4_workstations
) == 0)
241 PrintResourceString(IDS_GENERIC_ALL
);
243 PrintToConsole(L
"%s", pUserInfo
->usri4_workstations
);
244 PrintToConsole(L
"\n");
246 PrintPaddedResourceString(IDS_USER_LOGON_SCRIPT
, nPaddedLength
);
247 PrintToConsole(L
"%s\n", pUserInfo
->usri4_script_path
);
249 PrintPaddedResourceString(IDS_USER_PROFILE
, nPaddedLength
);
250 PrintToConsole(L
"%s\n", pUserInfo
->usri4_profile
);
252 PrintPaddedResourceString(IDS_USER_HOME_DIR
, nPaddedLength
);
253 PrintToConsole(L
"%s\n", pUserInfo
->usri4_home_dir
);
255 PrintPaddedResourceString(IDS_USER_LAST_LOGON
, nPaddedLength
);
256 if (pUserInfo
->usri4_last_logon
== 0)
257 PrintResourceString(IDS_GENERIC_NEVER
);
259 PrintDateTime(pUserInfo
->usri4_last_logon
);
260 PrintToConsole(L
"\n\n");
262 PrintPaddedResourceString(IDS_USER_LOGON_HOURS
, nPaddedLength
);
263 if (pUserInfo
->usri4_logon_hours
== NULL
)
264 PrintResourceString(IDS_GENERIC_ALL
);
265 PrintToConsole(L
"\n\n");
267 PrintToConsole(L
"\n");
268 PrintPaddedResourceString(IDS_USER_LOCAL_GROUPS
, nPaddedLength
);
269 if (dwLocalGroupTotal
!= 0 && pLocalGroupInfo
!= NULL
)
271 for (i
= 0; i
< dwLocalGroupTotal
; i
++)
274 PrintPadding(L
' ', nPaddedLength
);
275 PrintToConsole(L
"*%s\n", pLocalGroupInfo
[i
].lgrui0_name
);
280 PrintToConsole(L
"\n");
283 PrintPaddedResourceString(IDS_USER_GLOBAL_GROUPS
, nPaddedLength
);
284 if (dwGroupTotal
!= 0 && pGroupInfo
!= NULL
)
286 for (i
= 0; i
< dwGroupTotal
; i
++)
289 PrintPadding(L
' ', nPaddedLength
);
290 PrintToConsole(L
"*%s\n", pGroupInfo
[i
].grui0_name
);
295 PrintToConsole(L
"\n");
299 if (pGroupInfo
!= NULL
)
300 NetApiBufferFree(pGroupInfo
);
302 if (pLocalGroupInfo
!= NULL
)
303 NetApiBufferFree(pLocalGroupInfo
);
305 if (pUserModals
!= NULL
)
306 NetApiBufferFree(pUserModals
);
308 if (pUserInfo
!= NULL
)
309 NetApiBufferFree(pUserInfo
);
321 WCHAR szPassword1
[PWLEN
+ 1];
322 WCHAR szPassword2
[PWLEN
+ 1];
325 *lpAllocated
= FALSE
;
329 PrintResourceString(IDS_USER_ENTER_PASSWORD1
);
330 ReadFromConsole(szPassword1
, PWLEN
+ 1, FALSE
);
331 PrintToConsole(L
"\n");
333 PrintResourceString(IDS_USER_ENTER_PASSWORD2
);
334 ReadFromConsole(szPassword2
, PWLEN
+ 1, FALSE
);
335 PrintToConsole(L
"\n");
337 if (wcslen(szPassword1
) == wcslen(szPassword2
) &&
338 wcscmp(szPassword1
, szPassword2
) == 0)
340 ptr
= HeapAlloc(GetProcessHeap(),
342 (wcslen(szPassword1
) + 1) * sizeof(WCHAR
));
345 wcscpy(ptr
, szPassword1
);
353 PrintToConsole(L
"\n");
354 PrintResourceString(IDS_USER_NO_PASSWORD_MATCH
);
355 PrintToConsole(L
"\n");
370 BOOL bDelete
= FALSE
;
372 BOOL bDomain
= FALSE
;
374 LPWSTR lpUserName
= NULL
;
375 LPWSTR lpPassword
= NULL
;
376 PUSER_INFO_4 pUserInfo
= NULL
;
377 USER_INFO_4 UserInfo
;
381 BOOL bPasswordAllocated
= FALSE
;
382 NET_API_STATUS Status
;
386 Status
= EnumerateUsers();
387 printf("Status: %lu\n", Status
);
392 Status
= DisplayUser(argv
[2]);
393 printf("Status: %lu\n", Status
);
398 if (argv
[i
][0] != L
'/')
400 lpUserName
= argv
[i
];
401 // printf("User: %S\n", lpUserName);
405 if (argv
[i
][0] != L
'/')
407 lpPassword
= argv
[i
];
408 // printf("Password: %S\n", lpPassword);
412 for (j
= i
; j
< argc
; j
++)
414 if (_wcsicmp(argv
[j
], L
"/help") == 0)
416 PrintResourceString(IDS_USER_HELP
);
419 else if (_wcsicmp(argv
[j
], L
"/add") == 0)
423 else if (_wcsicmp(argv
[j
], L
"/delete") == 0)
427 else if (_wcsicmp(argv
[j
], L
"/domain") == 0)
429 PrintResourceString(IDS_ERROR_OPTION_NOT_SUPPORTED
, L
"/DOMAIN");
442 /* Interactive password input */
443 if (lpPassword
!= NULL
&& wcscmp(lpPassword
, L
"*") == 0)
445 ReadPassword(&lpPassword
,
446 &bPasswordAllocated
);
449 if (!bAdd
&& !bDelete
)
451 /* Modify the user */
452 Status
= NetUserGetInfo(NULL
,
455 (LPBYTE
*)&pUserInfo
);
456 if (Status
!= NERR_Success
)
458 printf("Status: %lu\n", Status
);
463 else if (bAdd
&& !bDelete
)
466 ZeroMemory(&UserInfo
, sizeof(USER_INFO_4
));
468 UserInfo
.usri4_name
= lpUserName
;
469 UserInfo
.usri4_password
= lpPassword
;
470 UserInfo
.usri4_flags
= UF_SCRIPT
| UF_NORMAL_ACCOUNT
;
472 pUserInfo
= &UserInfo
;
475 for (j
= i
; j
< argc
; j
++)
477 if (_wcsnicmp(argv
[j
], L
"/active:", 8) == 0)
480 if (_wcsicmp(p
, L
"yes") == 0)
482 pUserInfo
->usri4_flags
&= ~UF_ACCOUNTDISABLE
;
484 else if (_wcsicmp(p
, L
"no") == 0)
486 pUserInfo
->usri4_flags
|= UF_ACCOUNTDISABLE
;
490 PrintResourceString(IDS_ERROR_INVALID_OPTION_VALUE
, L
"/ACTIVE");
495 else if (_wcsnicmp(argv
[j
], L
"/comment:", 9) == 0)
497 pUserInfo
->usri4_comment
= &argv
[j
][9];
499 else if (_wcsnicmp(argv
[j
], L
"/countrycode:", 13) == 0)
502 value
= wcstoul(p
, &endptr
, 10);
505 PrintResourceString(IDS_ERROR_INVALID_OPTION_VALUE
, L
"/COUNTRYCODE");
510 /* FIXME: verify the country code */
512 pUserInfo
->usri4_country_code
= value
;
514 else if (_wcsnicmp(argv
[j
], L
"/expires:", 9) == 0)
517 if (_wcsicmp(p
, L
"never") == 0)
519 pUserInfo
->usri4_acct_expires
= TIMEQ_FOREVER
;
523 /* FIXME: Parse the date */
524 PrintResourceString(IDS_ERROR_OPTION_NOT_SUPPORTED
, L
"/EXPIRES");
527 else if (_wcsnicmp(argv
[j
], L
"/fullname:", 10) == 0)
529 pUserInfo
->usri4_full_name
= &argv
[j
][10];
531 else if (_wcsnicmp(argv
[j
], L
"/homedir:", 9) == 0)
533 pUserInfo
->usri4_home_dir
= &argv
[j
][9];
535 else if (_wcsnicmp(argv
[j
], L
"/passwordchg:", 13) == 0)
538 if (_wcsicmp(p
, L
"yes") == 0)
540 pUserInfo
->usri4_flags
&= ~UF_PASSWD_CANT_CHANGE
;
542 else if (_wcsicmp(p
, L
"no") == 0)
544 pUserInfo
->usri4_flags
|= UF_PASSWD_CANT_CHANGE
;
548 PrintResourceString(IDS_ERROR_INVALID_OPTION_VALUE
, L
"/PASSWORDCHG");
553 else if (_wcsnicmp(argv
[j
], L
"/passwordreq:", 13) == 0)
556 if (_wcsicmp(p
, L
"yes") == 0)
558 pUserInfo
->usri4_flags
&= ~UF_PASSWD_NOTREQD
;
560 else if (_wcsicmp(p
, L
"no") == 0)
562 pUserInfo
->usri4_flags
|= UF_PASSWD_NOTREQD
;
566 PrintResourceString(IDS_ERROR_INVALID_OPTION_VALUE
, L
"/PASSWORDREQ");
571 else if (_wcsnicmp(argv
[j
], L
"/profilepath:", 13) == 0)
573 pUserInfo
->usri4_profile
= &argv
[j
][13];
575 else if (_wcsnicmp(argv
[j
], L
"/scriptpath:", 12) == 0)
577 pUserInfo
->usri4_script_path
= &argv
[j
][12];
579 else if (_wcsnicmp(argv
[j
], L
"/times:", 7) == 0)
582 PrintResourceString(IDS_ERROR_OPTION_NOT_SUPPORTED
, L
"/TIMES");
584 else if (_wcsnicmp(argv
[j
], L
"/usercomment:", 13) == 0)
586 pUserInfo
->usri4_usr_comment
= &argv
[j
][13];
588 else if (_wcsnicmp(argv
[j
], L
"/workstations:", 14) == 0)
591 PrintResourceString(IDS_ERROR_OPTION_NOT_SUPPORTED
, L
"/WORKSTATIONS");
595 if (!bAdd
&& !bDelete
)
597 /* Modify the user */
598 Status
= NetUserSetInfo(NULL
,
603 printf("Status: %lu\n", Status
);
605 else if (bAdd
&& !bDelete
)
608 Status
= NetUserAdd(NULL
,
612 printf("Status: %lu\n", Status
);
614 else if (!bAdd
&& bDelete
)
616 /* Delete the user */
617 Status
= NetUserDel(NULL
,
619 printf("Status: %lu\n", Status
);
623 if (bPasswordAllocated
== TRUE
&& lpPassword
!= NULL
)
624 HeapFree(GetProcessHeap(), 0, lpPassword
);
626 if (!bAdd
&& !bDelete
&& pUserInfo
!= NULL
)
627 NetApiBufferFree(pUserInfo
);
630 PrintResourceString(IDS_USER_SYNTAX
);